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
CodePudding user response:
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();
}
});
CodePudding user response:
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"?