Java Collections.sort() not working even though comparable is declared

时间:2017-12-18 05:27:35

标签: java sorting comparable

Here is my interface class

public interface Thing {
    int getVolume();
}

And here is the class which implements Thing

Item.java

public class Item implements Thing, Comparable<Thing> {
    private String name;
    private int volume;

    public Item(String name,int volume){
        this.name = name;
        this.volume = volume;
    }

    @Override
    public int getVolume() {
        return this.volume;
    }

    public String getName(){
        return this.name;
    }

    @Override
    public String toString(){
        return name+" ("+volume+" dm^3)";
    }

 //   @Override
    @Override
    public int compareTo(Thing another) {
        if(this.getVolume()  < another.getVolume()){
            return -1;
        }

        if(this.getVolume() == another.getVolume()){
            return 0;
        }
        else{
            return 1;
        }
    }

}

When I try to run the main program with the following commands it runs fine // main program.java

public class Main {

    public static void main(String[] args) {
        // test your program here
     List<Item> items = new ArrayList<Item>();
    items.add(new Item("passport", 2));
    items.add(new Item("toothbrash", 1));
    items.add(new Item("circular saw", 100));

    Collections.sort(items);
    System.out.println(items);



    }
}

But when I try to run Collections.sort() on another class which implements the Thing interface, I get an error

here is the box class which implements the Thing interface and when I try to run the Collections.sort(store) in the void sort() function it gives an error even the store is a List and the Box class implements Thing interface and I have defined comparable for Thing in the Item.java class

Box.java

public class Box implements Thing {

    private int maximumCapacity;
    private List<Thing> store;

    public Box(int maximumCapacity) {
        this.maximumCapacity = maximumCapacity;
        this.store = new ArrayList<Thing>();
    }

    public boolean addThing(Thing thing) {
        // I.E. if the item added does not make the total volume go to max capacity only
        // then add
        if (this.getVolume() + thing.getVolume() < this.maximumCapacity) {
            store.add(thing);
            return true;
        }
        return false;
    }

    @Override
    public int getVolume() {
        // we calculate things of all items in the boxes (current value)
        int currentWeight = 0;
        for (Thing t : store) {
            currentWeight += t.getVolume();
        }
        return currentWeight;
    }

    public List<Thing> getStore() {
        return store;
    }

    public int numOfItems(){
        return this.store.size();
    }


     public void sort(){ 

        Collections.sort(store); // *****does not work ****//

     }

}

It gives an error above for sort as "No suitable method found for sort(List <Thing>)."

My question is if it can work in the main.java program where the items are given as List then why can it not work here ? How to fix it?

6 个答案:

答案 0 :(得分:3)

It the main class you sort a List<Item> where Item implements Thing, Comparable<Thing>.

In the Box class you try to sort List<Thing>, but Thing itself does not implement Comparable<Thing>. Therefore Java doesn't know how to sort Things.

To fix it you either have to provide a comparator for two Things (as proposed by Александр Нестеров) or you declare Thing implements Comparable<Thing>:

public interface Thing extends Comparable<Thing>{

    int getVolume();

    //provide default method to sort any class which implements Thing
    @Override
    public default int compareTo(Thing another) {
        return Integer.compare(this.getVolume(), another.getVolume());
    }
}

答案 1 :(得分:2)

It's because in first you sort "item", in second you sort "list thing"
So, you can fix it by using lambda:

Collections.sort(store, (o1, o2) -> {
your implementation of comparator
});

答案 2 :(得分:0)

I recommend you define Thing to extend Comparable, given your application doesn't work when you add classes not being Comparable.

By the way, your compareTo looks rather complicated. Do this instead:

int compareTo(Thing another) {
    return this.getVolume()  - another.getVolume();
    }

答案 3 :(得分:0)

In the first program, you have

public class Item implements Thing, Comparable<Thing>

But in the second, you just have

public class Box implements Thing

If you want sort to work, you need to either implement Comparable or Comparator (separate class implementing just Comparator).

答案 4 :(得分:0)

If you are using jdk 8 or above and want all classes implementing "Thing" should be sorted on the bases of same parameter you should change your interface to this to provide default sorting capability:

//extend your interface with comparable

public interface Thing extends Comparable<Thing>{

int getVolume();

//provide default method to sort any class which implements Thing
@Override
public default int compareTo(Thing another) {
    if(this.getVolume()  < another.getVolume()){
        return -1;
    }

    if(this.getVolume() == another.getVolume()){
        return 0;
    }
    else{
        return 1;
    }
}

}

Now Item and Box only needs to implement Thing interface.

Please try to optimize compareTo() method also as suggested by @Jo Witters

答案 5 :(得分:-1)

Make Thing an abstract class implementing Comparable , so that Thing is always ready for sorting . Item can be extended from Thing