如何按对象的ArrayList<Integer>属性对对象集合进行多优先级排序?
如何按对象的ArrayList属性对对象集合进行多优先级排序?
这个需求在多维度排序场景里太常见了,就像你举的奥运奖牌排序例子——先比金牌数,金牌相同再比银牌,最后比铜牌。咱们可以用Java里的Comparator接口或者让类实现Comparable来搞定,下面给你几种实用的方案:
方案一:自定义Comparator(最灵活,适合临时排序需求)
如果这个排序只是某次业务场景需要,不是类的默认排序逻辑,直接写个自定义比较器就好。核心思路就是按ArrayList的索引顺序依次比较,优先级从高到低:
// 假设你已经有了一个List<OlympicWinner> olympicWinners列表 Collections.sort(olympicWinners, (o1, o2) -> { // 先比金牌数:金牌多的排前面,所以用o2和o1比较(降序) int goldCompare = Integer.compare(o2.getMedals().get(0), o1.getMedals().get(0)); if (goldCompare != 0) { return goldCompare; } // 金牌数相同,比银牌数 int silverCompare = Integer.compare(o2.getMedals().get(1), o1.getMedals().get(1)); if (silverCompare != 0) { return silverCompare; } // 银牌数也相同,最后比铜牌数 return Integer.compare(o2.getMedals().get(2), o1.getMedals().get(2)); });
要是你需要升序(比如奖牌少的排前面),把o2和o1的位置调换就行。
方案二:让类实现Comparable(适合默认排序逻辑)
如果这个奖牌排序是OlympicWinner类的自然排序规则(比如每次排序都按这个规则来),那让类实现Comparable接口更方便,以后排序不用重复写比较器:
修改你的OlympicWinner类:
public class OlympicWinner implements Comparable<OlympicWinner> { // 原有的属性、构造方法、getName()、getMedals()不变 @Override public int compareTo(OlympicWinner other) { // 同样按金牌→银牌→铜牌的优先级降序比较 int goldCompare = Integer.compare(other.getMedals().get(0), this.getMedals().get(0)); if (goldCompare != 0) { return goldCompare; } int silverCompare = Integer.compare(other.getMedals().get(1), this.getMedals().get(1)); if (silverCompare != 0) { return silverCompare; } return Integer.compare(other.getMedals().get(2), this.getMedals().get(2)); } }
之后排序直接调用:
Collections.sort(olympicWinners); // 或者用List自带的sort方法 olympicWinners.sort(null);
方案三:Java 8+链式比较器(代码更简洁)
Java 8给Comparator加了thenComparing系列方法,可以链式组合多个比较规则,代码更清爽:
// 构建链式比较器 Comparator<OlympicWinner> medalComparator = Comparator // 按金牌数降序(用负号实现降序) .comparingInt(o -> -o.getMedals().get(0)) // 金牌相同,按银牌数降序 .thenComparingInt(o -> -o.getMedals().get(1)) // 银牌相同,按铜牌数降序 .thenComparingInt(o -> -o.getMedals().get(2)); // 执行排序 olympicWinners.sort(medalComparator);
你也可以用reversed()方法来反转排序方向,但要注意链式调用时的顺序,用负号的方式会更直观,不容易出错。
通用扩展:适配任意长度的ArrayList
如果你的medals列表可能不止3个元素(比如以后加了其他奖牌类型),可以写个通用的比较逻辑,循环遍历两个列表的元素,直到找到第一个不相等的元素:
Collections.sort(olympicWinners, (o1, o2) -> { List<Integer> medals1 = o1.getMedals(); List<Integer> medals2 = o2.getMedals(); int minLength = Math.min(medals1.size(), medals2.size()); // 按索引顺序依次比较 for (int i = 0; i < minLength; i++) { int compareResult = Integer.compare(medals2.get(i), medals1.get(i)); if (compareResult != 0) { return compareResult; } } // 如果前面的元素都相等,可根据需求决定列表长度的排序规则(这里是长列表排前面) return Integer.compare(medals2.size(), medals1.size()); });
这样不管列表有多少个元素,都能按优先级从高到低排序,非常灵活。
备注:内容来源于stack exchange,提问作者user16393738
相关产品推荐
相关产品推荐

