如何按属性对对象的数组列表进行排序?

39
假设你有一个由 HockeyPlayer 对象组成的 Arraylist。如果它们都有一个名为int goalsScored的变量,你该如何按照goalsScored排序呢?

3
这里有一些需要翻译的内容:Dupe: https://dev59.com/NXI-5IYBdhLWcg3whYsr, https://dev59.com/SXNA5IYBdhLWcg3wn_U1, https://dev59.com/KnM_5IYBdhLWcg3w1G-N and more. 这些链接是关于如何对ArrayList进行排序的问题。 - BalusC
7个回答

96

您可以使用Collections.sort与自定义的Comparator<HockeyPlayer>

    class HockeyPlayer {
        public final int goalsScored;
        // ...
    };

    List<HockeyPlayer> players = // ...

    Collections.sort(players, new Comparator<HockeyPlayer>() {
        @Override public int compare(HockeyPlayer p1, HockeyPlayer p2) {
            return p1.goalsScored - p2.goalsScored; // Ascending
        }

    });

比较部分也可以这样写:

players.sort(Comparator.comparingInt(HockeyPLayer::goalsScored));

或者,您可以使HockeyPlayer implementsComparable<HockeyPlayer>。这定义了所有HockeyPlayer对象的自然排序。使用Comparator更加灵活,因为不同的实现可以按名称、年龄等排序。

另请参阅


为了完整性,我应该警告说,由于可能的溢出(即:Effective Java第二版:第12项:考虑实现Comparable),必须极度谨慎地使用return o1.f - o2.f减法比较快捷方式。大概冰球不是一种可以得分导致问题的运动 =)
另请参阅:

自己进球算负分吗?因为如果“goalsScored”严格为正,那么减法技巧就没问题了。 - polygenelubricants
自己的进球算作是最后一个接触冰球的对方球员的进球,因此“goalsScored”永远不会为负数。即使它是负数,我认为减法技巧仍然有效。 - Matthew
9
return p1.goalsScored - p2.goalsScored; 可以被替换为 return Integer.compare(p1.goalsScored,p2.goalsScored);,以避免在 goalsScored 可能具有负值时发生整数溢出。此外,自 Java 8 开始,此代码可以被替换为 Collections.sort(players, Comparator.comparingInt(h -> h.goalsScored)); - Pshemo
@Pshemo 很棒的解决方案,你的解决方案修复了一个类似的问题。 - user443346
1
@Pshemo 谢谢,当我要比较的属性是长整型时,这很有用 - 我可以使用 return Long.compare(p1.getLongValue(), p2.getLongValue()); - user1318194

7

正如@user6158055所建议的那样,使用Java 8可以实现一行代码,如下:

Collections.sort(
                hockeyPlayerList,
                (player1, player2) -> player1.getGoalsScored()
                        - player2.getGoalsScored());

完整的示例如下所示,以说明同样的内容:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<HockeyPlayer> hockeyPlayerList = new ArrayList<>();
        hockeyPlayerList.add(new HockeyPlayer("A", 3));
        hockeyPlayerList.add(new HockeyPlayer("D", 10));
        hockeyPlayerList.add(new HockeyPlayer("B", 2));

        System.out.println("Before Sort based on goalsScored\n");

        hockeyPlayerList.forEach(System.out::println);

        System.out.println("\nAfter Sort based on goalsScored\n");

        Collections.sort(
                hockeyPlayerList,
                (player1, player2) -> player1.getGoalsScored()
                        - player2.getGoalsScored());

        hockeyPlayerList.forEach(System.out::println);
    }

    static class HockeyPlayer {

        private String name;
        private int goalsScored;

        public HockeyPlayer(final String name, final int goalsScored) {
            this.name = name;
            this.goalsScored = goalsScored;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public int getGoalsScored() {
            return goalsScored;
        }

        public void setGoalsScored(int goalsScored) {
            this.goalsScored = goalsScored;
        }

        @Override
        public String toString() {
            return "HockeyPlayer [name=" + name + ", goalsScored="
                    + goalsScored + "]";
        }

    }
}

输出:

Before Sort based on goalsScored

HockeyPlayer [name=A, goalsScored=3]
HockeyPlayer [name=D, goalsScored=10]
HockeyPlayer [name=B, goalsScored=2]

After Sort based on goalsScored

HockeyPlayer [name=B, goalsScored=2]
HockeyPlayer [name=A, goalsScored=3]
HockeyPlayer [name=D, goalsScored=10]

5

只需要一行Java 8代码:

Collections.sort(players, (p1, p2) -> p1.getGoalsScored() - p2.getGoalsScored());

1
如何对字符串数据类型的属性执行相同操作。 - cammando
1
顺便说一句,我找到了一种按字符串排序的方法Collections.sort( people, (player1, player2) -> player1.getLastName().compareTo(player2.getLastName()) ); - cammando

3
编写定制的Comparator来完成此任务。要了解更多信息,请参见Comparator

2

1
使用Java 8很简单。
Collections.sort(playList, Comparator.comparingInt(HockeyPLayer::goalsScored))

0

Java 有一组 sort() 方法可以用于这种排序。详见 Collections.sort (和 Comparable)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接