我正在创建一个程序,它接收两个.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问题的细节。
与@Pedro Borges 的答案相同,但是......。
Iterator.remove()
来删除当前值,而不是使用源集合。这就是你得到一个 ConcurrentModificationException
.Map.Entry
,您可以使用 keySet()
而不是。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();
}
}
你也可以考虑重构你的读词方式。
如同。
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),以避免开箱从 Integer
到 int
的性能原因。
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();
你将不再有并发的修改。