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?
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);
}
}
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
.
Try this.
public class Comparator_Test {
public static void main(String[] args) {
ArrayList<Players> list = new ArrayList<Players>();
Players p1 = new Players(1,92,"Zlatan");
Players p2 = new Players(2,92,"Hazard");
Players p3 = new Players(1,82,"Klose");
list.add(p1);
list.add(p2);
list.add(p3);
PlayerComparator comparator = new PlayerComparator();
System.out.println(list);
Collections.sort(list, comparator);
System.out.println(list);
}
}
class Players {
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);
}
public String toString() {
return rating + "";
}
}
class PlayerComparator implements Comparator<Players> {
@Override
public int compare(Players o1, Players o2) {
if(o1.rating > o2.rating) {
return 1;
}
if(o1.rating < o2.rating) {
return -1;
}
return 0;
}
}