如何在arraylist中找到最常见的20个单词

时间:2019-09-25 08:46:35

标签: java sorting arraylist hashmap

我有一个任务,给我一个带有文本的文件。那段文字是一本书的一部分。我的任务是将该文件传输到我做过的arraylist,hashmap(其中之一)中。工作的第二部分是从该文件中找到20个最常见的单词,并按降序对其进行排序。

到目前为止,我将文件中的所有这些单词插入了hashmap和arraylist中(下面提供了代码),我在单独的方法中完成了这两个操作。 hashmap方法仅返回数字,而arraylist仅返回具有重复次数的最常见单词。

所以第一部分代码将是哈希图

public void findWords() throws Exception {
    // ovde traxim 20 reci koje se najcesce ponavljaju u tekstu
    String line;
    Integer counter = 0;
    FileReader fr = new FileReader("src/Fajl/blab");
    BufferedReader br = new BufferedReader(fr);

    while ((line = br.readLine()) != null) {
        String string[] = line.toLowerCase().split("([,.\\s]+)");
        for (String s : string) {
            if (hashmap.containsKey(s)) {
                counter++;
            } else
                counter = 1;
            hashmap.put(s, counter);
        }
    }

接下来的部分是按值排序,并显示从前到后的前20个单词的重复次数

Collection<Integer> values = mapaKnjiga.values();
    ArrayList<Integer> list = new ArrayList<Integer>(values);
    Collections.sort(list, Collections.reverseOrder());
    for (int i = 0; i < 20; i++)
        System.out.println(list.get(i));
}

6 个答案:

答案 0 :(得分:1)

将单词作为哈希表,将单词作为键并计为值。

LinkedHashMap<String, Integer> reverseSortedMap = new LinkedHashMap<>();

words.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .forEachOrdered(x -> reverseSortedMap.put(x.getKey(), x.getValue()));

List<String> finalList = reverseSortedMap.entrySet()
                                        .stream()
                                        .map(entry -> entry.getKey())
                                        .limit(20)
                                        .collect(Collectors.toList());

答案 1 :(得分:0)

您可以创建一个TextCounter类,然后根据地图收集的数据将其添加到列表中

class TextCounter{
  String text;
  int count;
}

现在按他的计数值排序

答案 2 :(得分:0)

假设您想要列表中前20个单词及其频率,从文件中读取单词,则Java-8解决方案应该是

LinkedHashMap<String, Long> top20WordsByFrequency = null;
    try {
        // Convert a file into stream of lines
        top20WordsByFrequency = Files.lines(Paths.get("src/Fajl/blab"))
                // convert lines into words
                .flatMap(line -> Arrays.stream(line.toLowerCase().split("([,.\\\\s]+)")))
                // make a map by grouping by key as word and value as the count of the word
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())).entrySet().stream()
                // sort the map based on values (frequency) in reverse order and limit the map
                // to 20
                .sorted(Entry.comparingByValue(Comparator.reverseOrder())).limit(20)
                // after limiting sort based on keys in descending order
                .sorted(Map.Entry.<String, Long>comparingByKey().reversed())
                // preserve the order in a LinkedHashMap
                .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (u, v) -> u, LinkedHashMap::new));

    } catch (IOException e) {
        e.printStackTrace();
    }
    System.out.println(top20WordsByFrequency);

答案 3 :(得分:0)

如何使用流API:

String[] words = {"one", "two", "two", "three", "three", "three"};
Map<String, Long> result = 
        Arrays.stream(words)
              .collect(Collectors.groupingBy(Function.identity(),
                       Collectors.counting()));

第二部分:

List<Long> collect = result.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .limit(20)
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());
System.out.println(collect);

答案 4 :(得分:0)

假设您的findWords()函数正常运行,并且您拥有所有单词及其计数,则可以继续以下操作:

因为您必须打印特定单词的计数。因此,您可以首先定义一个具有属性内容和计数的Word类,并定义一个默认的比较器。类似这样的事情:

class Item implements Comparable<Item>{
   String word;
   int count;

public Item(String word, int count){
    this.count = count;
    this.word = word;
}

public int compareTo(Item word){
    //sorting in descending order
    return word.count - this.count;
}

public String toString(){
    return "Word: " + word +"Count: " + count;
}}

定义项的ArrayList来容纳Item对象:

ArrayList<Item> al = new ArrayList<>();

您可以遍历整个哈希图,然后将每对插入为:

Item item = new Item(word, count);
al.add(item);

最后,您可以对列表进行排序,然后选择前20个单词:

Collections.sort(al);

答案 5 :(得分:0)

感谢大家的努力,并会为您提供帮助。 我是Java编程的初学者,目前正在为课程做最后的项目。 我找到了解决方案,在我看来,如果您使用的是此解决方案,则很难理解。这不是我的解决方案,但可以。 首先,我用文件中的值填充哈希图,然后检查该单词是否已存在于文件中,如果为true counter ++,如果为false counter = 1。之后

public void dvadesetNajviseKoriscenih() throws Exception{
    // this is where I populate hashmap with values
    String line;
    Integer counter = 0;
    FileReader fr = new FileReader("src/Fajl/knjiga");
    BufferedReader br = new BufferedReader(fr);

    while ((line = br.readLine()) != null) {
        String string[] = line.toLowerCase().split(" ");
        for (String s : string) {
            // this is where I check if the word already exists
            if (hashmapName.containsKey(s)) {
                counter++; //however this counter here is not right, so I will have to change it.
            } else
                counter = 1;
            hashmapName.put(s, counter);
        }
    } //this below is where it sorts words by number of how many times it repeats...

    Map<String, Integer> sorted = hashmapName.entrySet().stream().sorted(comparingByValue())
            .collect(toMap(e -> e.getKey(), e -> e.getValue(), (e1, e2) -> e2, LinkedHashMap::new));
    sorted = hashmapName.entrySet().stream().sorted(Collections.reverseOrder(Map.Entry.comparingByValue()))
            .limit(20).collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e2, LinkedHashMap::new));
    for (String s : sorted.keySet()) {
        System.out.println(s + " " + sorted.get(s));
    }
}

如果有人知道代码底部的内容,请随意向我们解释,新手:) 当然,请为我的解决方案评分:) 如果有人想练习这个任务,请随时在github / BojanBosnjak

上写信给我。