问题
I'm new to java, and I'm not really getting how to use the comparator interface.
I have an ArrayList
of Item
s 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:
- The
@Override
annotation should not be mandatory. If Eclipse wants you to put it on, don't worry. - 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 thepublic 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