遇到并发ModificationException。遇到并发ModificationException. 我的迭代器和HashMaps出了点问题,我不知道是什么原因。

问题描述 投票:0回答:2

我正在创建一个程序,它接收两个.txt文件,并打印出两个文本中出现的单词以及每个共享单词在每个文本中出现的次数。我声明了两个具有有效路径的文件对象。然而,当我试图创建两个使用两个.txt文件的Scanner对象时,我在声明新的Scanner对象的两行代码中都得到了FileNotFoundException编译器错误。

顺便说一下,我在一个 while 循环中使用 scannerObject.hasNext(),将 scannerObject.Next()中的每个单词作为一个新的键添加到 HashMap 变量中,其值为 1,如果该单词已经是 HashMap 中的一个键,则将其值(出现次数)增加 1。

我试着用两种文件路径运行下面的程序,下面的简单程序运行时没有错误,并输出 "It worked! Hehehe"。

import java.io.*;
import java.util.*;

public class readingFilesPractice {
    public static void main(String[] args) {
        try{
            File x = new File("C:\\Users\\aravd.000\\Desktop\\Book1.txt");
            Scanner sc = new Scanner(x);
            while(sc.hasNext()){
                System.out.println(sc.next());
            }
            sc.close();
            System.out.println("It worked! Hehehe");
        }
        catch (Exception e){
            System.out.println("Error!");
        }
    }
}

顺便说一下,在.txt文件中,有一些地方连续出现了多个空格,还有类似 "1 "的东西。

下面的代码运行时遇到两个FileNotFoundExceptions(没有try和catch块),在Visual Studios中。new Scanner(book1)new Scanner(book2) 有一行红色的方格线,当我用鼠标悬停在它上面时,上面写着 "Unhandled异常类型FileNotFoundExceptionJava(16777384)"。下面是我的完整代码供参考。

import java.io.*;
import java.util.*;

public class program1 {
    public static void main(String[] args) {
        try {
            File book1 = new File("C:\\Users\\aravd.000\\Desktop\\Book1.txt");
            File book2 = new File("C:\\Users\\aravd.000\\Desktop\\Book2.txt");


            // Counting the number of occurences of each word in book1
            Scanner readBook1 = new Scanner(book1);
            HashMap<String, Integer> wordsInBook1 = new HashMap<String, Integer>();
            while (readBook1.hasNext()) {
                String word = readBook1.next();
                if (wordsInBook1.containsKey(word)) {
                    int occurences = wordsInBook1.get(word) + 1;
                    wordsInBook1.put(word, occurences);
                } else {
                    wordsInBook1.put(word, 1);
                }
            }
            readBook1.close();

            // Counting the number of occurences of each word in book2
            Scanner readBook2 = new Scanner(book2);
            HashMap<String, Integer> wordsInBook2 = new HashMap<String, Integer>();
            while (readBook2.hasNext()) {
                String word = readBook2.next();
                if (wordsInBook2.containsKey(word)) {
                    int occurences = wordsInBook2.get(word) + 1;
                    wordsInBook2.put(word, occurences);
                } else {
                    wordsInBook2.put(word, 1);
                }
            }
            readBook2.close();

            // Creating two iterators for each HashMap
            Iterator wordsInB1Iter = wordsInBook1.entrySet().iterator();
            Iterator wordsInB2Iter = wordsInBook2.entrySet().iterator();

            // Running the wordsInB1Iter iterator to find and delete unique keys in
            // wordsInBook1
            while (wordsInB1Iter.hasNext()) {
                Map.Entry pair = (Map.Entry) wordsInB1Iter.next();
                if (!wordsInBook2.containsKey(pair.getKey())) {
                    wordsInBook1.remove(pair.getKey());
                }
            }

            // Running the wordsInB2Iter iterator to find and delete unique keys
            while (wordsInB2Iter.hasNext()) {
                Map.Entry pair = (Map.Entry) wordsInB2Iter.next();
                if (!wordsInBook1.containsKey(pair.getKey())) {
                    wordsInBook2.remove(pair.getKey());
                }
            }
            System.out.println(wordsInBook1);
            System.out.println(wordsInBook2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

如果代码的其他部分坏了,我就不知道了,因为我还没有调试过。如果你发现其他地方有错误,如果你愿意,请告诉我。谢谢你的努力,如果有什么需要进一步说明的地方,请告诉我!

更新:当我把我的捕获块改为Exception e并使用e.printStackTrace时,我的代码输出了以下内容。

java.util.ConcurrentModificationException
        at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
        at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1526)
        at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1524)
        at prorgam1.main(program1.java:50)

链接到VisualStudios中 "PROBLEMS "选项卡中的错误描述。

上面的图片可能会提供更多关于我的迭代器和HashMaps问题的细节。

java compiler-errors java.util.scanner filenotfoundexception
2个回答
1
投票

与@Pedro Borges 的答案相同,但是......。

  • 请使用通用名! 你的代码中充满了铸造,而它不应该。
  • 请使用 Iterator.remove() 来删除当前值,而不是使用源集合。这就是你得到一个 ConcurrentModificationException.
  • 如果你不需要 Map.Entry,您可以使用 keySet() 而不是。
  • 你使用的是Java > 8.如果这是Java 11,你也可以使用 var.

你的代码。

        Iterator<Map.Entry<String, Integer>>> wordsInB1Iter = wordsInBook1.entrySet().iterator();
        Iterator<Map.Entry<String, Integer>>> wordsInB2Iter = wordsInBook2.entrySet().iterator();

        // Running the wordsInB1Iter iterator to find and delete unique keys in
        // wordsInBook1
        while (wordsInB1Iter.hasNext()) {
            Map.Entry<String,Integer> pair = wordsInB1Iter.next();
            if (!wordsInBook2.containsKey(pair.getKey())) {
                wordsInB1Iter.remove();
            }
        }

        // Running the wordsInB2Iter iterator to find and delete unique keys
        while (wordsInB2Iter.hasNext()) {
            Map.Entry<String,Integer> pair = wordsInB2Iter.next();
            if (!wordsInBook1.containsKey(pair.getKey())) {
                wordsInB2Iter.remove();
            }
        }

你也可以考虑重构你的读词方式。

  • 通过使用一个方法来代替重复的代码。
  • 通过使用try与资源(Java 7++)。
  • 通过使用Map.merge (Java 8++)

如同。

void words(File file) {
  try (Scanner scanner = new Scanner(file)) {
    var result = new HashMap<String,Integer>();
    while (scanner.hasNext()) {
      var word = scanner.next();
      result.merge(word, 1, Integer::sum); // or (a, b) -> a + b
    }
    return result;
  }
}

你可以(应该?MutableInteger (来自common-lang3),以避免开箱从 Integerint 的性能原因。


0
投票

ConcurrentModificationException来自于你在迭代Set时从Set中移除元素的事实。发生这种情况的原因是,迭代器是由集合支持的,而不是它的副本。

有一种方法可以解决这个问题,虽然不是很优雅,但是可以在Set的副本上进行迭代。

如果你把

Iterator wordsInB1Iter = wordsInBook1.entrySet().iterator();
Iterator wordsInB2Iter = wordsInBook2.entrySet().iterator();

Iterator wordsInB1Iter = new HashSet<>(wordsInBook1.entrySet()).iterator();
Iterator wordsInB2Iter = new HashSet<>(wordsInBook2.entrySet()).iterator();

你将不再有并发的修改。

© www.soinside.com 2019 - 2024. All rights reserved.