简体   繁体   中英

How to read strings off of .txt file and sort them into an ArrayList based on the number of occurrences?

I have a program that reads a .txt file, creates a HashMap containing each unique string and its number of occurrences, and I would like to create an ArrayList that displays these unique strings in descending order in terms of their number of appearances.

Currently, my program sorts in descending order from an alphabetical standpoint (using ASCII values I assume).

How can I sort this in descending order in terms of their number of appearances?

Here's the relevant part of the code:

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

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

First read the file using the Files.lines method which gives your a Stream<String> of the lines.

Now collect the lines into a Map<String, Integer> using the Map.merge method which takes a key and a value and also a lambda that is applied to the old value and the new value if the key is already present.

You now have your counts.

Now take a Stream of the entrySet of the Map and sort that by the value of each Entry and then take the key . Collect that to a List . You now have a List of your values sorted by count.

Now simply use forEach to print them.

If still using Java 7 you can use the Map to provide the sort order:

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

You haven't shown the declaration of your map, but for the purpose of this answer I'm assuming that your map is declared like this:

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

You need to use a Comparator in the call to sort, but it needs to compare by the count, while remembering the string. So you need to put objects in the list that have both the string and the count. One type that provides this capability, and that is easily available from the Map.entrySet method, is the type Map.Entry .

The last part rewritten with Map.Entry and a Comparator :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM