How to use the Comparator interface

匆匆过客 提交于 2019-11-29 02:50:10

问题


I'm new to java, and I'm not really getting how to use the comparator interface. I have an ArrayList of Items in an Inventory class and an Item class. In the Item class I wrote:

public class Item implements Comparator<Item> {
    //stuff
    ...
    @Override
    public int compare(Item a, Item b) {
        if (a.getID().compareToIgnoreCase(b.getID())>0)
            return 1;
        else if (a.getID().compareToIgnoreCase(b.getID())<0)
            return -1;
        else
            return 0;
    }
}

The getID() method just gives the id, which I have to use to alphabetize the items. I'm not sure if this is right, it made me put the @Override annotation, I'm not sure why. Also I wrote an interface that just says:

 public interface Comparator<Item>
{
    int compare(Item a, Item b);
}

I'm not sure about that bit. Also how do I implement this method to sort the arraylist created in the inventory class?

Thanks, if my question doesn't make sense or needs clarification just let me know.


回答1:


To use the Comparator interface you have to implement it and pass it as an anonymous class to Collections.sort(List list, Comparator c) as the second parameter.

If you want to pass only the list to Collections.sort(List list) then your Item class has to the implement Comparable interface.

So in both cases the Collections.sort methods know how to order the elements in your list

here is some sample code:

Item class implementing Comparable + Inventory holding a list of items

public class Item implements Comparable<Item> {

    String id = null;

    public Item(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return id;
    }

    @Override
    public int compareTo(Item o) {
        return - id.compareToIgnoreCase(o.id);
    }
}


public class Inventory {

    List<Item> items = new ArrayList<>();

    public void addItem(Item item) {
        items.add(item);
    }

    public static void main(String[] args) {
        Inventory inventory = new Inventory();
        inventory.addItem(new Item("2"));
        inventory.addItem(new Item("4"));
        inventory.addItem(new Item("1"));
        inventory.addItem(new Item("7"));

        Collections.sort(inventory.items, new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                return o1.id.compareToIgnoreCase(o2.id);
            }
        });
        System.out.println(inventory.items);

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

    }
}

Output

[1, 2, 4, 7] // ascending
[7, 4, 2, 1] // descending since the compareTo method inverts the sign of the comparison result.



回答2:


EDIT: First of all, a couple of things:

  1. The @Override annotation should not be mandatory. If Eclipse wants you to put it on, don't worry.
  2. Don't write your own Comparator interface. Delete that definition NAO and use the one provided by Java. Reinventing the wheel probably violates the Unspoken Code of Computer Programming in about 15 different ways. Use import java.util.Comparator; at the very top of your code (before the public class stuff) to a) use the version given by Java and b) make your code compatible with pretty much everything else that exists in the world.

The Comparator interface is not used to create a class that can put itself in order. This is the Comparable interface.

Both are similar, so I will describe both here.

java.util.Comparator

The Comparator interface, as you already know, has one method: compare. Comparator is generic (uses the angle brackets <>) and takes the type it will compare inside the <>. The thing is that Comparators are used to compare items of other classes. For example, I could create a Comparator for java.lang.Integers that returns the opposite of the "natural order" (how Integers are usually ordered).

Comparators are used mostly to give other objects a way to sort their parameters when they are not in natural order. For example, the java.util.TreeSet class takes a Comparator for its sorting capability.

java.lang.Comparable

Comparable's purpose is to say that an object can be compared. It is also generic and takes the type that it can be compared to. For example, a Comparable<String> can be compared to Strings.

Comparable has one method: compareTo(). Unlike Comparator's compare(), compareTo takes one parameter. It works like compare, except it uses the invoking object as one parameter. So, comparableA.compareTo(comparableB) is the same as comparator.compare(comparableA, comparableB).

Comparable mostly establishes the natural order for objects, and is the default way to compare objects. Comparator's role is to override this natural order when one has different needs for data comparison or sorting.

ArrayList Sorting

To sort a List, you could use the method already available: scroll down to sort on the java.util.Collections class. One method takes a Comparator, the other does not. sort is static; use Collections.sort(...), not Collections c = new Collections(); c.sort(...). (Collections doesn't even have a constructor anyway, so meh.)




回答3:


You are mixing up the interfaces Comparator and Comparable.

Comparator: http://docs.oracle.com/javase/6/docs/api/java/util/Comparator.html

Comparable: http://docs.oracle.com/javase/6/docs/api/java/lang/Comparable.html

The purpose of Comparator is a class (declared anonymously on the spot or otherwise) that can be passed to an operation that needs an ordering, and it defines the sort that will be used on the item. Comparator is to be used OUTSIDE of the class that needs sorting, if there is an alternative way you want to sort it by.

The purpose of Comparable is to say that the class (that implements Comparable) has a natural ordering - and this is what it is. If your class that needs sorting has a natural ordering, then define it as Comparable. (A class that implements Comparable's sort order can still be overriden by a Comparator. On the other hand, if the class is not Comparable than also passing a Comparator is mandatory for ordering to be possible.)




回答4:


You've implemented the wrong interface, you want Comparable




回答5:


Use of @Override annotation is a standard practice in editors like eclipse, netbeans to notify developer that he is overriding/implementing parent class/interface method. It is optional.

Don't implement this interface in your Item class. Create a new class and implement the Comparator interface.

public class ItemCompare implements Comparator<Item> {

    @Override
    public int compare(Item a, Item b) {
        if (a.getID().compareToIgnoreCase(b.getID())>0)
            return 1;
        else if (a.getID().compareToIgnoreCase(b.getID())<0)
            return -1;
        return 0;
    }
} 

And then, in your main class, do this:

ArrayList al = new ArrayList<Item>

Collections.sort(al, new ItemCompare())


来源:https://stackoverflow.com/questions/16126563/how-to-use-the-comparator-interface

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!