Java, how to use compareTo to sort an Arraylist
Solution 1
Instead of making Player
implement Comparable
, you get more flexibility by implementing Comparator<Player>
classes. For example:
class PlayerComparatorByRating implements Comparator<Player> {
@Override
public int compare(Player o1, Player o2) {
return o1.getRating() - o2.getRating();
}
}
class PlayerComparatorByName implements Comparator<Player> {
@Override
public int compare(Player o1, Player o2) {
return o1.getName().compareTo(o2.getName());
}
}
After all, Player
has multiple fields, it's easy to imagine that sometimes you might want to order players differently. A great advantage of this approach is the single responsibility principle: a Player
class does only one thing, encapsulates player data. Instead of adding one more responsibility (sorting), it's better to move that logic in another class.
You could use these comparators with Collections.sort
, for example:
Collections.sort(list, new PlayerComparatorByRating());
System.out.println(list);
Collections.sort(list, new PlayerComparatorByName());
System.out.println(list);
Extra tips
Your class seems to be named Players
. It's better to rename to Player
.
The getName
, getRating
, getPos
methods should not return void
and print the result, but return the field values instead.
Use better names for the constructor arguments, for example:
Player(int position, int rating, String name) {
this.position = position;
this.rating = rating;
this.name = name;
}
Use the right type of list to store players:
List<Player> list = new ArrayList<Player>();
Please format your code properly. Any IDE can do that.
Suggested implementation
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
class Player {
private int position;
private int rating;
private final String name;
Player(int position, int rating, String name) {
this.position = position;
this.rating = rating;
this.name = name;
}
public int getRating() {
return rating;
}
public int getPos() {
return position;
}
public String getName() {
return name;
}
@Override
public String toString() {
return String.format("%s:%d:%d", name, position, rating);
}
}
class PlayerComparatorByRating implements Comparator<Player> {
@Override
public int compare(Player o1, Player o2) {
return o1.getRating() - o2.getRating();
}
}
class PlayerComparatorByName implements Comparator<Player> {
@Override
public int compare(Player o1, Player o2) {
return o1.getName().compareTo(o2.getName());
}
}
public class PlayerComparatorDemo {
public static void main(String[] args){
List<Player> list = new ArrayList<Player>();
Player p1 = new Player(1, 92, "Zlatan");
Player p2 = new Player(2, 92, "Hazard");
Player p3 = new Player(1, 82, "Klose");
list.add(p1);
list.add(p2);
list.add(p3);
Collections.sort(list, new PlayerComparatorByRating());
System.out.println(list);
Collections.sort(list, new PlayerComparatorByName());
System.out.println(list);
}
}
Solution 2
Don't use a raw type with Comparable
. Instead, use Comparable<Players>
. This way, you have direct access to the object you care about without having to cast from Object
.
The sample compareTo
would be this:
public int compareTo(Player other) {
return rating - other.getRating();
}
Then, you would actually have to...sort it, using Collections.sort()
.
Collections.sort(list);
The reason for Comparable<Players>
is that Comparable
itself is defined as taking a generic type T
.
Admin
Updated on July 27, 2020Comments
-
Admin almost 4 years
Im trying to figure out how to sort an ArrayList using comparable, my code looks like this:
public class playerComparsion{ public static void main(String[] args){ ArrayList<Object> list = new ArrayList<Object>(); Player p1 = new Players(1,92,Zlatan); Player p2 = new Players(2,92,Hazard); Player p3 = new Players(1,82,Klose); list.add(p1); list.add(p2); list.add(p3); } } class Players implements Comparable{ int position; String name; int rating; public Players(int i, int j, String string) { this.position=i; this.rating=j; this.name=string; } public void getRating() { System.out.println(this.rating); } public void getPos() { System.out.println(this.position); } public void getName() { System.out.println(this.name); } @Override public int compareTo(Object o) { // TODO Auto-generated method stub return 0; } }
I want to sort the Arraylist based on the attribute rating. I suppose I should use the compareTo function but I have no idea how, can someone help me?
-
fabian almost 10 yearsYou can access rating directly, if you do it from any method in
Player
, even for another instance, i.e.other.rating
can be used instead ofother.getRating()
. Also it should be mentioned that the substraction may overflow and produce a illegal value if negative ratings are allowed. -
Admin almost 10 yearsI dont understand how to USE the compareTo function. I want to sort the Arraylist "list".
-
Makoto almost 10 yearsThe thing is, it's not you that is using the
compareTo
function. You're only honoring the contract that you need to establish forCollections.sort()
to work properly. It's actuallyCollections.sort()
that makes use of yourcompareTo
method, since it only sorts things that areComparable
. The way you would call it would beCollections.sort(list)
, but I'll add that into the answer. -
D. Ben Knoble about 9 yearsJust browsing arround; should you do a null check in your compare methods??
-
janos over 8 yearsGood question. If you allow null values in your collections, then yes, you must add null checks.
-
Jay Wong over 8 yearsCould you please explain a little bit more about why writing
return rating - other.getRating();
? I am totally confused about the compareto function. -
Makoto over 8 years@JayWong: The link in the answer above takes you to the documentation for
Comparable
. The main principle is that it has to return a negative, zero, or a positive number for less than, equal, or greater than. Subtracting the two fields we care about is the quickest way to accomplish that, provided the values don't underflow. -
Jay Wong over 8 years@Makoto: Thank you. Can I interpret like the
Collections.sort()
actually is comparing the return value of mycompareTo
function to achieve sorting? -
MNM about 8 yearsNice, I liked what you did here very infomative