【问题标题】:How to read strings off of .txt file and sort them into an ArrayList based on the number of occurrences?如何从 .t​​xt 文件中读取字符串并根据出现次数将它们排序到 ArrayList 中?
【发布时间】:2014-07-25 08:46:10
【问题描述】:

我有一个程序可以读取 .txt 文件,创建一个包含每个唯一字符串及其出现次数的 HashMap,我想创建一个 ArrayList 以按出现次数降序显示这些唯一字符串.

目前,我的程序从字母顺序的角度降序排序(使用我假设的 ASCII 值)。

如何按出现次数降序排列?

这是代码的相关部分:

            Scanner in = new Scanner(new File("C:/Users/ahz9187/Desktop/counter.txt"));
            while(in.hasNext()){
                String string = in.next();


             //makes sure unique strings are not repeated - adds a new unit if new, updates the count if repeated
                if(map.containsKey(string)){
                    Integer count = (Integer)map.get(string);
                    map.put(string, new Integer(count.intValue()+1));
                } else{
                    map.put(string, new Integer(1));
                }
            }
            System.out.println(map);

            //places units of map into an arrayList which is then sorted
            //Using ArrayList because length does not need to be designated - can take in the units of HashMap 'map' regardless of length

            ArrayList arraylist = new ArrayList(map.keySet());
            Collections.sort(arraylist);                      //this method sorts in ascending order

            //Outputs the list in reverse alphabetical (or descending) order, case sensitive

            for(int i = arraylist.size()-1; i >= 0; i--){ 
                String key = (String)arraylist.get(i);

                Integer count = (Integer)map.get(key);
                System.out.println(key + " --> " + count);
            }

【问题讨论】:

  • 使用自定义Comparator。从HashMap获取出现次数并比较...
  • 并使用 entrySet() 而不是 keySet(),所以你有唯一的字符串和出现的次数。
  • 使用 Comparator 将完成的 HashMap 中的所有项目推入 PriorityQueue,就像 Boris 所说的那样。你想要的是一个最大堆,所以一旦你把所有东西都放入了 priqueue(按出现次数排序),你就可以poll() 直到你提取所有元素。
  • 旁注:Integer 支持+ 运算符:map.put(string, map.get(string) + 1);。 @BoristheSpider 你为什么不回答而不是评论?
  • @sp00m 如果你坚持的话。

标签: java sorting arraylist hashmap counter


【解决方案1】:

您尚未显示地图的声明,但出于此答案的目的,我假设您的地图是这样声明的:

Map<String,Integer> map = new HashMap<String,Integer>();

您需要在调用中使用Comparator 进行排序,但它需要按计数进行比较,同时记住字符串。因此,您需要将具有字符串和计数的对象放入列表中。 Map.entrySet 方法提供了这种能力,并且很容易获得这种类型,即Map.Entry

最后一部分用Map.EntryComparator重写:

ArrayList<Map.Entry<String,Integer>> arraylist = new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
Collections.sort(arraylist, new Comparator<Map.Entry<String,Integer>>() {
    @Override
    public int compare(Entry<String, Integer> e1, Entry<String, Integer> e2) {
        // Compares by count in descending order
        return e2.getValue() - e1.getValue();
    }
});

// Outputs the list in reverse alphabetical (or descending) order, case sensitive

for (Map.Entry<String,Integer> entry : arraylist) {
    System.out.println(entry.getKey() + " --> " + entry.getValue());
}

【讨论】:

  • 这是完美的。谢谢。
【解决方案2】:

在 Java 8 中:

public static void main(final String[] args) throws IOException {
    final Path path = Paths.get("C:", "Users", "ahz9187", "Desktop", "counter.txt");
    try (final Stream<String> lines = Files.lines(path)) {
        final Map<String, Integer> count = lines.
                collect(HashMap::new, (m, v) -> m.merge(v, 1, Integer::sum), Map::putAll);
        final List<String> ordered = count.entrySet().stream().
                sorted((l, r) -> Integer.compare(l.getValue(), r.getValue())).
                map(Entry::getKey).
                collect(Collectors.toList());
        ordered.forEach(System.out::println);
    }
}

首先使用Files.lines 方法读取文件,该方法为您提供Stream&lt;String&gt; 的行数。

现在使用Map.merge 方法将这些行收集到Map&lt;String, Integer&gt; 中,该方法接受一个键和一个值以及一个应用于旧值和新值(如果键已经存在)的 lambda。

你现在有你的计数了。

现在从MapentrySet 中取一个Stream,然后按每个Entryvalue 对其进行排序,然后再取key。将其收集到List。您现在有一个按计数排序的值的List

现在只需使用forEach 打印它们。

如果仍在使用 Java 7,您可以使用 Map 来提供排序顺序:

final Map<String, Integer> counts = /*from somewhere*/
final List<String> sorted = new ArrayList<>(counts.keySet());
Collections.sort(sorted, new Comparator<String>() {

    @Override
    public int compare(final String o1, final String o2) {
        return counts.get(o1).compareTo(counts.get(o2));
    }
});

【讨论】:

    猜你喜欢
    • 2020-10-01
    • 1970-01-01
    • 2019-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 2020-06-21
    相关资源
    最近更新 更多