简体   繁体   中英

Sorting of Arraylist using Collections.sort and comparetor

The scenario is I have brand_name, model_no and price of mobile company and I have to sort it according to the brand_name of mobile. And I am using Collections.sort for natural sorting and comparetor for custom sorting but due to some issue this code is not compiling. Please any one can help me to fix this problem

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class ArrayListSortingExample {
   private static class SmartPhone implements Comparable {
    private String brand;
    private String model;
    private int price;
    public SmartPhone(String brand, String model, int price){
        this.brand = brand;
        this.model = model;
        this.price = price;
    }
    @Override
    public int compareTo(SmartPhone sp) {
        return this.brand.compareTo(sp.brand);
    }
    @Override
    public String toString() {
        return "SmartPhone{" + "brand=" + brand + ", model=" + model + ", price=" + price + '}';
    }
}
private static class PriceComparator implements Comparator{
    @Override
    public int compare(SmartPhone sp1, SmartPhone sp2) {
        return (sp1.price < sp2.price ) ? -1: (sp1.price > sp2.price) ? 1:0 ;
    }
}
public static void main(String... args) {
    SmartPhone apple = new SmartPhone("Apple", "IPhone4S",1000);
    SmartPhone nokia = new SmartPhone("Nokia", "Lumia 800",600);
    SmartPhone samsung = new SmartPhone("Samsung", "Galaxy Ace",800);
    SmartPhone lg = new SmartPhone("LG", "Optimus",500);
    ArrayList Phones = new ArrayList();
    Phones.add(apple);
    Phones.add(nokia);
    Phones.add(samsung);
    Phones.add(lg);
    Collections.sort(Phones);
    System.out.println(Phones);
    Collections.sort(Phones, new PriceComparator());
    System.out.println(Phones);
}
}

The Output should be like this:

[SmartPhone{brand=Apple, model=IPhone4S, price=1000}, SmartPhone{brand=LG, model=Optimus, price=500}, SmartPhone{brand=Nokia, model=Lumia 800, price=600}, SmartPhone{brand=Samsung, model=Galaxy Ace, price=800}]

[SmartPhone{brand=LG, model=Optimus, price=500}, SmartPhone{brand=Nokia, model=Lumia 800, price=600}, SmartPhone{brand=Samsung, model=Galaxy Ace, price=800}, SmartPhone{brand=Apple, model=IPhone4S, price=1000}]

the error is

Exception in thread "main" java.lang.AbstractMethodError: employee.ArrayListSortingExample$SmartPhone.compareTo(Ljava/lang/Object;)I
at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at java.util.Collections.sort(Collections.java:155)
at employee.ArrayListSortingExample.main(ArrayListSortingExample.java:37)

Comparable and Comparator are both generic interfaces, you should implement them by putting 'implements Comparable < T >', with T being the class you put in the method compareTo. As you have not specified a T it is taking it as being Object, therefore by putting SmartPhone as the argument in compareTo you are not actually using the method you have contracted to use by implementing Comparable. In your code if you put Comparable< SmartPhone > and Comparator< SmartPhone > then your code should compile.

The problem is that the SmartPhone class implements Comparable , but the compareTo method takes an argument of type SmartPhone , and compareTo is declared as taking an Object . You can fix this problem by changing the compareTo in SmartPhone to the following:

@Override
public int compareTo(Object o) {
    SmartPhone sp = (SmartPhone) o;
    return this.brand.compareTo(sp.brand);
}

This code works because this method will never be called with an argument of type other than SmartPhone unless you make a mistake and put something other than SmartPhone in the array list.


You can avoid all these problems with the use of generics . With generics your code becomes this:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class ArrayListSortingExample {
   private static class SmartPhone implements Comparable<SmartPhone> {
    private String brand;
    private String model;
    private int price;
    public SmartPhone(String brand, String model, int price){
        this.brand = brand;
        this.model = model;
        this.price = price;
    }
    @Override
    public int compareTo(SmartPhone sp) {
        return this.brand.compareTo(sp.brand);
    }
    @Override
    public String toString() {
        return "SmartPhone{" + "brand=" + brand + ", model=" + model + ", price=" + price + '}';
    }
}
private static class PriceComparator implements Comparator<SmartPhone> {
    @Override
    public int compare(SmartPhone sp1, SmartPhone sp2) {
        return (sp1.price < sp2.price ) ? -1: (sp1.price > sp2.price) ? 1:0 ;
    }
}
public static void main(String... args) {
    SmartPhone apple = new SmartPhone("Apple", "IPhone4S",1000);
    SmartPhone nokia = new SmartPhone("Nokia", "Lumia 800",600);
    SmartPhone samsung = new SmartPhone("Samsung", "Galaxy Ace",800);
    SmartPhone lg = new SmartPhone("LG", "Optimus",500);
    ArrayList<SmartPhone> Phones = new ArrayList<SmartPhone>();
    Phones.add(apple);
    Phones.add(nokia);
    Phones.add(samsung);
    Phones.add(lg);
    Collections.sort(Phones);
    System.out.println(Phones);
    Collections.sort(Phones, new PriceComparator());
    System.out.println(Phones);
}
}

For a full explanation of generics, see the Java Tutorial for Generics .

You should replace implements Comparable with Comparable<SmartPhone> , and implements Comparator with Comparator<SmartPhone> . Comparator and Comparable interfaces use generics. So you need to specify the type that you want compare.

Moreover ArrayList Phones = new ArrayList(); isn't nice because you're using a raw type and a bad name (uppercase is for class). Replace with ArrayList<SmartPhone> phones = new ArrayList<SmartPhone>(); . Generics are useful and prevent you from casting exceptions at runtime. If you are using JAVA SE 7 use the diamond operator ArrayList<SmartPhone> phones = new ArrayList<>();

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