什么时候使用 Comparable 和 Comparator

我有一个需要在字段上排序的对象列表,比如 Score。我没有多想就编写了一个新的类,它实现了 COMPATOR,完成了这个任务,并且工作正常。

现在回过头来看这个问题,我想知道我是否应该使用我的类实现 Comparable,而不是创建一个新的类来实现 Comparator。得分是对象排序的唯一字段。

  1. 我所做的事情可以作为一种实践来接受吗?

  2. 正确的方法是“首先让类实现 Compaable (用于自然排序) ,如果需要替代字段比较,那么创建一个实现 Compaator 的新类”吗?

  3. 如果上面的(2)是真的,那么这是否意味着只有在类实现了 Compaable 之后才应该实现 Compaator?(假设我拥有原来的类)。

127432 次浏览

这里也有一个类似的问题: 什么时候一个类应该是 Comparable 和/或 Comparator?

我想说的是: Implement Comparable for something like a natural ordering, e.g. based on an internal ID

实现一个比较器,如果你有一个更复杂的比较算法,例如多个字段等。

使用 Comparable如果你想定义一个 违约(自然的)排序行为的对象的问题,一个常见的做法是使用一个技术或自然的(数据库?)对象的标识符。

如果要定义 可外部控制的排序行为,请使用 Comparator,这可以覆盖默认的排序行为。

参见:

I would say that an object should implement Comparable if that is the clear natural way to sort the class, and anyone would need to sort the class would generally want to do it that way.

但是,如果排序是该类的一种不寻常的用法,或者排序只对特定用例有意义,那么比较器是一个更好的选择。

换句话说,给定类名,是否清楚可比排序是如何进行的,还是必须阅读 javadoc?如果是后者,那么未来的每个排序用例都可能需要一个比较器,这时候类比的实现可能会降低类用户的速度,而不是提高他们的速度。

Use Comparable:

  • 如果对象在您的控制中。
  • 如果比较行为是主要的比较行为。

Use Comparator :

  • 如果对象在您的控制范围之外,并且您不能让它们实现 Comparable
  • when you want comparing behaviour different from the default (which is specified by Comparable) behaviour.

我会说:

  • 如果比较是直观的,那么尽一切可能实现 Comparable
  • 如果不清楚你的比较是否直观,使用一个比较器,因为它更多 显而易见,因此对于必须维护代码的可怜的灵魂来说更加清晰
  • 如果有一个以上的直观比较可能,我更喜欢一个比较器, 可能由要比较的类中的工厂方法构建。
  • 如果比较是特殊用途,则使用 Compator
  • If at the moment of writing the class 您只有一个排序用例 使用可比对象。
  • 只有当你有一个以上的时候 排序策略实现一个 比较器。

当比较同一类的实例时,应使用可比较实例。

Comparator can be used to compare instances of different classes.

Comparable is implemented by the class which needs to define a natural ordering for its objects. 例如,String 实现了 Comparable。

In case a different sorting order is required, then, implement comparator and define its own way of comparing two instances.

非常简单的方法是假设有问题的实体类在数据库中表示,然后在数据库表中需要由实体类的字段组成的索引吗?如果答案是肯定的,那么实现可比性,并使用索引字段进行自然排序顺序。在所有其他情况下使用比较器。

如果需要自然顺序排序——用户可比较 如果您需要自定义订单排序-使用比较器

Example:

Class Employee{
private int id;
private String name;
private String department;
}

Natural order Sorting would be based on id because it would be unique and custom order sortin g would be name and department.

参考文献:
什么时候一个类应该是 Comparable 和/或 Comparator? Http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html

Comparable:
当我们只想存储同类元素和默认的自然排序顺序时,我们可以使用类实现 comparable接口。

比较器:
无论何时我们想要存储同质和异构的元素,并且我们想要按照默认的自定义排序顺序进行排序,我们都可以使用 comparator接口。

实现 ComparableComparator的注释库:

public class Person implements Comparable<Person> {
private String firstName;
private String lastName;
private int age;
private char gentle;


@Override
@CompaProperties({ @CompaProperty(property = "lastName"),
@CompaProperty(property = "age",  order = Order.DSC) })
public int compareTo(Person person) {
return Compamatic.doComparasion(this, person);
}
}

单击链接查看更多示例。 Http://code.google.com/p/compamatic/wiki/compamaticbyexamples

我的需求是根据日期排序的。

所以,我使用了类比,它很容易为我工作。

public int compareTo(GoogleCalendarBean o) {
// TODO Auto-generated method stub
return eventdate.compareTo(o.getEventdate());
}

一个限制是,它们不能用于 List 以外的集合。

如果你拥有这个班级,最好选择 可比的。通常,如果您不拥有这个类,但是必须使用 树集树木地图,那么就使用 比较器,因为在 TreeSet 或 TreeMap 的构造函数中,比较器可以作为参数传递。您可以在 http://preciselyconcise.com/java/collections/g_comparator.php中看到如何使用 Compaator 和 Compaable

Comparator does everything that comparable does, plus more.

比较器 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 用于允许 Collections.sort 工作 | yes | yes Can compare multiple fields | yes | yes Lives inside the class you’re comparing and serves | | 作为默认的比较方式 可以在课堂之外生活,你比较 | 不 | 是的 可以有多个具有不同方法名称的实例 输入参数可以是 | just Object | Any 类型的列表 可以使用 enum | no | yes

我发现将比较器作为匿名类使用的最佳方法如下:

private static void sortAccountsByPriority(List<AccountRecord> accounts) {
Collections.sort(accounts, new Comparator<AccountRecord>() {


@Override
public int compare(AccountRecord a1, AccountRecord a2) {
return a1.getRank().compareTo(a2.getRank());
}
});
}

您可以在计划排序的类中创建此类方法的多个版本。所以你可以拥有:

  • 排序
  • SortAccountsByType
  • SortAccountsByPriorityAndType

    等等。

现在,您可以在任何地方使用这些排序方法,并获得代码重用。 This gives me everything a comparable would, plus more ... so I don’t see any reason to use comparable at all.

可比 -java.lang.Comparable: int compareTo(Object o1)

A comparable object is capable of comparing itself with another object. The class itself must implements the java.lang.Comparable interface in order to be able to compare its instances.

  • 能够将当前对象与提供的对象进行比较。
  • 通过使用它,我们可以基于实例属性实现 only one sort sequence。 例子: Person.id
  • Some of the Predefined Classes like String, Wrapper classes, Date, Calendar has implemented Comparable interface.

比较器 -java.util.Comparator: int compare(Object o1, Object o2)

比较器对象能够比较两个不同的对象。该类不比较其实例,而是比较其他类的实例。这个比较器类必须实现 java.util。比较器接口。

  • Capable of comparing any two Objects of Same Type.
  • 通过使用它,我们可以实现 many sort sequence,并根据实例属性为每个实例命名。 例子: Person.id, Person.name, Person.age
  • 我们可以实现比较器接口到我们的预定义类自定义排序。

Example:

public class Employee implements Comparable<Employee> {


private int id;
private String name;
private int age;
private long salary;


// Many sort sequences can be created with different names.
public static Comparator<Employee> NameComparator = new Comparator<Employee>() {
@Override
public int compare(Employee e1, Employee e2) {
return e1.getName().compareTo(e2.getName());
}
};
public static Comparator<Employee> idComparator = new Comparator<Employee>() {
@Override
public int compare(Employee e1, Employee e2) {
return Integer.valueOf(e1.getId()).compareTo(Integer.valueOf(e2.getId()));
}
};


public Employee() { }
public Employee(int id, String name, int age, long salary){
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
// setters and getters.


// Only one sort sequence can be created with in the class.
@Override
public int compareTo(Employee e) {
//return Integer.valueOf(this.id).compareTo(Integer.valueOf(e.id));
//return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
if (this.id > e.id) {
return 1;
}else if(this.id < e.id){
return -1;
}else {
return Character.toString(this.name.charAt(0)).compareToIgnoreCase(Character.toString(e.name.charAt(0)));
}


}


public static void main(String[] args) {


Employee e1 = new Employee(5, "Yash", 22, 1000);
Employee e2 = new Employee(8, "Tharun", 24, 25000);


List<Employee> list = new ArrayList<Employee>();
list.add(e1);
list.add(e2);
Collections.sort(list); // call @compareTo(o1)
Collections.sort(list, Employee.nameComparator); // call @compare (o1,o2)
Collections.sort(list, Employee.idComparator); // call @compare (o1,o2)
}
}
  • 对于自定义的排序,我们在其他场景中使用 compator@compareTo (o1,o2) ,如果我们想对多个字段进行排序,我们不需要更改代码,而是使用 compator。

关于 Java8 Lambda: 比较器请参考我的文章。

在一次面试中,我被要求在比非登记时间更长的时间内对一定范围的数字进行排序。(不使用计数排序)

在对象上实现类比接口允许隐式排序算法使用重写的 compareTo 方法对排序元素进行排序,这将是线性时间。

以下几点可以帮助您决定在哪些情况下应该使用 Comparable,以及在哪些情况下应该使用 Comparator:

1)可用密码

2)单一与多重排序准则

3) Arays.sort ()和 Collection.sort ()

4) As keys in SortedMap and SortedSet

5)更多的类与灵活性

6)类间比较

7) Natural Order

更详细的文章,你可以参考 何时使用比较器和何时使用比较器

如果对象的排序需要基于自然顺序,那么使用 Compaable,而如果需要对不同对象的属性进行排序,那么使用 Java 中的 Compaator。

可比对象和比较器的主要区别:

+------------------------------------------------------------------------------------+
¦               Comparable                ¦                Comparator                ¦
¦-----------------------------------------+------------------------------------------¦
¦ java.lang.Comparable                    ¦ java.util.Comparator                     ¦
¦-----------------------------------------+------------------------------------------¦
¦ int objOne.compareTo(objTwo)            ¦ int compare(objOne, objTwo)              ¦
¦-----------------------------------------+------------------------------------------¦
¦ Negative, if objOne < objTwo            ¦ Same as Comparable                       ¦
¦ Zero,  if objOne == objTwo              ¦                                          ¦
¦ Positive,  if objOne > objTwo           ¦                                          ¦
¦-----------------------------------------+------------------------------------------¦
¦ You must modify the class whose         ¦ You build a class separate from to sort. ¦
¦ instances you want to sort.             ¦ the class whose instances you want       ¦
¦-----------------------------------------+------------------------------------------¦
¦ Only one sort sequence can be created   ¦ Many sort sequences can be created       ¦
¦-----------------------------------------+------------------------------------------¦
¦ Implemented frequently in the API by:   ¦ Meant to be implemented to sort          ¦
¦ String, Wrapper classes, Date, Calendar ¦ instances of third-party classes.        ¦
+------------------------------------------------------------------------------------+

对于数值是升序的和字符串是字母顺序的,默认的自然排序顺序是可比的。 例如:

Treeset t=new Treeset();
t.add(2);
t.add(1);
System.out.println(t);//[1,2]

比较器是通过重写比较方法在自定义 myCOMPator 类中实现的自定义排序顺序 例如:

Treeset t=new Treeset(new myComparator());
t.add(55);
t.add(56);
class myComparator implements Comparator{
public int compare(Object o1,Object o2){
//Descending Logic
}
}
System.out.println(t);//[56,55]