sort and group a java collection

前端 未结 5 501
无人及你
无人及你 2021-02-01 21:17

I have an object which has a name and a score. I would like to sort a collection of such objects so that they are grouped by name and sorted by maximum score in each group (and

5条回答
  •  旧时难觅i
    2021-02-01 22:14

    Foreach over the collection, and put the objects into a Map>, keyed by name, where the SortedSet is a TreeSet with a custom comparator that compares by score.

    Then foreach over the map's values() collection, and put the groups into a SortedSet>, with a second custom comparator that compares SortedSets according to their largest element. Actually, instead of foreaching, you can simply use addAll().

    Here's the code:

    public class SortThings {
    
        static class Thing {
            public final String name;
            public final int score;
            public Thing(String name, int score) {
                this.name = name;
                this.score = score;
            }
            @Override
            public String toString() {
                return "(" + name + ", " + score + ")";
            }
        }
    
        public static void main(String[] args) {
            Collection things = Arrays.asList(
                new Thing("a", 3),
                new Thing("a", 9),
                new Thing("b", 7),
                new Thing("b", 10),
                new Thing("c", 8),
                new Thing("c", 3)
            );
    
            SortedSet> sortedGroups = sortThings(things);
    
            System.out.println(sortedGroups);
        }
    
        private static SortedSet> sortThings(Collection things) {
            final Comparator compareThings = new Comparator() {
                public int compare(Thing a, Thing b) {
                    Integer aScore = a.score;
                    Integer bScore = b.score;
                    return aScore.compareTo(bScore);
                }
            };
    
            // first pass
            Map> groups = new HashMap>();
            for (Thing obj: things) {
                SortedSet group = groups.get(obj.name);
                if (group == null) {
                    group = new TreeSet(compareThings);
                    groups.put(obj.name, group);
                }
                group.add(obj);
            }
    
            // second pass
            SortedSet> sortedGroups = new TreeSet>(new Comparator>() {
                public int compare(SortedSet a, SortedSet b) {
                    return compareThings.compare(a.last(), b.last());
                }
            });
            sortedGroups.addAll(groups.values());
            return sortedGroups;
        }
    
    }
    

    Note that the output is in smallest-to-largest order. That's the natural order with Java's collections; it would be trivial to modify this to sort the other way if that's what you need.

提交回复
热议问题