有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何从中读取字符串。txt文件,并根据出现的次数将其排序到ArrayList中?

我有一个程序可以读取。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);
            }

共 (2) 个答案

  1. # 1 楼答案

    在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<String>

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

    你现在有你的计数了

    现在从{}的{}中取一个{},然后按每个{}的{}排序,然后取{}。把它收集到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));
        }
    });
    
  2. # 2 楼答案

    您还没有显示地图的声明,但为了回答这个问题,我假设您的地图声明如下:

    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());
    }