简体   繁体   中英

How to sort a List of generic objects

I'm struggling with sorting an ArrayList of a generic objects.

I've tried to do it with Comparable interface, but it doesn't work, I've also tried with sort method of collections, but I'm still at the same point.

public class League<T extends Player> implements LeagueComparator<T> {
    private String name;

    private ArrayList<Team<T>> teams = new ArrayList<>();
    public void ranking(){
        for (Team<T> team : teams){
            System.out.println(team.getName() + team.ranking());
            int ranking = team.ranking();

            Collections.sort(teams, new Comparator<Team<T>>() {
                @Override
                public int compare(Team<T> o1, Team<T> o2) {
                    return 

In this method, I want to take a ranking integer from Team class and sort it, and then return the sorted values

public class Team<T extends Player> {
    private int size = 0;
    private String name;
    private int games;
    private int win;
    private int lose;
    private int draw;

    private ArrayList<T> members = new ArrayList<>();

    public int ranking(){
        return (win * 2) + draw;
    }

This is Team class EDIT

    System.out.println(team.ranking() + " " + team.getName());         
    Collections.sort(teams, Comparator.comparingInt(team::rankings));  
    System.out.println(team.ranking() + " " + team.getName());        

Now it throws

Exception in thread "main"
java.util.ConcurrentModificationException

Simply returns the difference in ranking of o1 and o2.

Collections.sort(teams, new Comparator<Team<T>>() {
  @Override
  public int compare(Team<T> o1, Team<T> o2) {
    return o1.ranking() - o2.randking();
  }
});

Comparable

I tried with Comparable interface but it doesn't work

If there's only one way to compare teams that make sense from the perspective of your application - by their ranking , then Team objects have a natural ordering and hence class Team should implement Comparable .

A quote from the documentation :

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class's natural ordering , and the class's compareTo method is referred to as its natural comparison method .

That's how it might be done:

public static class Team<T extends Player> implements Comparable<Team<T>> {
    public static final Comparator<Team<? extends Player>> BY_TEAM_RANKING =
        Comparator.comparingInt(Team::ranking);
    
    // fields, getters, etc.

    public int ranking() {
        return (win * 2) + draw;
    }

    @Override
    public int compareTo(Team<T> other) {
        return BY_TEAM_RANKING.compare(this, other);
    }
}

For the sake of conciseness, method compareTo in the code shown above internally uses Comparator defined as a static field ( similar approach you can find in the book "Effective Java" by Joshua Bloch, have a look at it for more information on implementing Comparable interface ).

To sort the list of teams , use method sort() directly on the list (which is a more fluent alternative of Collection.sort() introduced with Java 8).

public class League<T extends Player> {
    
    private String name;
    private List<Team<T>> teams = new ArrayList<>();
    
    public void ranking() {
        teams.sort(null); // teams are comparable, hence no need to provide a comparator and null is passed as an argument
    }
}

Comparators

In case if there are multiple ways how teams need to be sorted in different scenarios, then Team class should not implement Comparable , don't go with way.

You can define comparators for different use-cases as public static fields in the Team class, like below:

public static class Team<T extends Player> {
    
    public static final Comparator<Team<? extends Player>> BY_TEAM_RANKING =
        Comparator.comparingInt(Team::ranking);
    
    public static final Comparator<Team<? extends Player>> BY_TEAM_NAME =
        Comparator.comparing(Team::getName);
    
    // the rest code
}

And then apply them depending on a particular case:

public void ranking() {
    teams.sort(Team.BY_TEAM_RANKING);
}

Sidenote: write your code against interfaces, not implementations like ArrayList . See What does it mean to "program to an interface"?

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