问题描述
我正在遍历几个文本文件,并且试图在所有文本文件中找到前20个单词。我设法建立了一些代码来在单个文件中找到前20个单词。但是,现在我在处理几个文件。
我有一个全局的链接哈希表,我想将遇到的每个新单词(作为键)存储在文本文件中,并希望在遇到更多新单词时更新其值(出现的次数)这个词。例如,在第一个文件中,我找到8000个单词“ the”的实例,在下一个文件中,我在另一个文件中遇到7000个“ the”实例,然后我希望将键“ the”的值更新为15000
这是我的代码:
import java.util.*;
import java.util.stream.Collectors;
import java.io.IOException;
import java.nio.file.*;
import java.util.Map.Entry;
import java.util.function.Function;
import java.io.File;
import java.nio.charset.StandardCharsets;
public class FileReaderTwo
{
static LinkedHashMap<String,Long> top20Words = null;
public static void main(String args[])
{
File dir = new File("data/");
for (File file : dir.listFiles())
{
try
{
top20Words = Files.lines(Paths.get(file.toString()),StandardCharsets.ISO_8859_1)
.flatMap(line -> Arrays.stream(line.toLowerCase().split("[\\(,\\).\\s+]+")))
.collect(Collectors.groupingBy(Function.identity(),Collectors.counting())).entrySet().stream()
.sorted(Entry.comparingByValue(Comparator.reverSEOrder()))
.sorted(Map.Entry.<String,Long>comparingByValue().reversed())
.collect(Collectors.toMap(Entry::getKey,Entry::getValue,(u,v) -> u,LinkedHashMap::new));
} catch (IOException e)
{
e.printstacktrace();
}
}
System.out.println(top20Words);
}
}
注意:我知道目前它打印出每个单词,我想先处理此问题,然后再解决。
解决方法
好的,我修改了此代码以执行我认为您要寻找的操作。其工作原理如下。
- 创建了两种方法来简化文件访问处理异常。与尝试在流中放置try类构造相反,我不仅推荐此方法更简单,更简洁。
- 获取所有单词并进行频率计数并将其存储在地图中。
- 对地图的entrySet进行排序,并以降序排列地图中的前20个字(最高字数)。
总体结果是对多个文件中的所有单词进行计数,然后按降序显示提示。
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class FileWordCount {
public static void main(String[] args) {
FileWordCount fwc = new FileWordCount();
Map<String,Long> map = fwc.getTheWords();
map.entrySet().forEach(System.out::println);
}
// helper methods to handle exceptions.
private Stream<Path> getFiles(String dir) {
try {
return Files.list(Path.of(dir));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private Stream<String> getLines(Path path) {
try {
return Files.lines(path,StandardCharsets.ISO_8859_1);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public Map<String,Long> getTheWords() {
String dir = "f:./data";
return getFiles(dir)
.flatMap(this::getLines)
.flatMap(line -> Arrays.stream(
line.toLowerCase().split("[\\(,\\).\\s+]+")))
.collect(Collectors.groupingBy(word -> word,Collectors.counting()))
.entrySet().stream()
.sorted(Entry.<String,Long>comparingByValue().reversed().
thenComparing(Entry.<String,Long>comparingByKey()))
.limit(20) // limts the number of entries
.collect(Collectors.toMap(Entry::getKey,Entry::getValue,(r,u)->r,LinkedHashMap::new));
}
}
注意。我首先按相反的顺序对计数进行排序,然后,如果出现平局,则按正常的字母顺序进行排序。
,首先,不要将旧的File
API与新的NIO.2 API混合使用。
您可以从Stream
个文件开始,合并所有文件的结果。
Path dir = Paths.get("data/");
LinkedHashMap<String,Long> top20Words = Files.list(dir)
.filter(path -> ! Files.isDirectory(path))
.flatMap(file -> {
try {
return Files.lines(file,StandardCharsets.ISO_8859_1);
} catch (IOException e) {
e.printStackTrace();
return Stream.empty();
}
})
// the rest is copied from question,to show context
.flatMap(line -> Arrays.stream(line.toLowerCase().split("[\\(,\\).\\s+]+")))
.collect(Collectors.groupingBy(Function.identity(),Collectors.counting())).entrySet().stream()
.sorted(Entry.comparingByValue(Comparator.reverseOrder()))
.sorted(Map.Entry.<String,Long>comparingByValue().reversed())
.collect(Collectors.toMap(Entry::getKey,(u,v) -> u,LinkedHashMap::new));
System.out.println(top20Words);