何时使用Comparable和Comparator
我有一个列表,我需要在字段上sorting,比如Score。 没有太多的想法,我写了一个实现比较器的新类,它完成任务并且工作。
现在回顾一下,我想知道是否应该让我的类实现Comparable而不是创build一个实现Comparator的新类。 分数是对象将被sorting的唯一字段。
-
我做了什么可以接受的做法?
-
是正确的方法“首先有类实现Comparable(对于自然顺序),如果需要替代字段比较,然后创build一个新的类,实现Comparator”?
-
如果(2)是真的,那么是否意味着只有在类实现Comparable后才能实现Comparator? (假设我拥有原始类)。
如果这是对类进行sorting的明确的自然方法,那么我会说一个对象应该实现Comparable,而任何需要对类进行sorting的人通常都希望这样做。
但是,如果sorting是class级的不寻常使用,或者sorting只对特定用例有意义,那么比较器是更好的select。
换一种说法,给定类名,是否可以比较类似的问题,还是必须诉诸阅读javadoc呢? 如果是后者,则每个分类用例都需要一个比较器,在这一点上,可比较的实现可能会降低该类用户的速度,而不能加速他们的速度。
如果要定义有问题的对象的默认 (自然)sorting行为,则使用Comparable
,通常的做法是使用该对象的技术或自然(数据库?)标识符。
如果要定义外部可控sorting行为,请使用Comparator
,这可以覆盖默认sorting行为。
使用Comparable
:
- 如果对象在你的控制之下。
- 如果比较行为是主要的比较行为。
使用Comparator
:
- 如果对象不在你的控制范围之内,你不能使它们实现
Comparable
。 - 当您想要比较行为不同于默认(由
Comparable
指定)行为时。
当你比较同一类的实例时,应该使用Comparable。
比较器可以用来比较不同类别的实例。
Comparable是由需要为其对象定义自然sorting的类实现的。 像String实现Comparable。
如果需要不同的sorting顺序,那么他可以实现比较器并定义自己的比较两个实例的方法。
比较器可以做所有可比较的事情,再加上更多。
| | Comparable | Comparator ._______________________________________________________________________________ Is used to allow Collections.sort to work | yes | yes Can compare multiple fields | yes | yes Lives inside the class you're comparing and serves | | as a “default” way to compare | yes | yes Can live outside the class you're comparing | no | yes Can have multiple instances with different method names | no | yes Input arguments can be a list of | just Object| Any type Can use enums | 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()); } }); }
您可以在您计划sorting的课程内部创build多个此类方法的版本。 所以你可以有:
- sortAccountsByPriority
- sortAccountsByType
-
sortAccountsByPriorityAndType
等等…
现在,您可以在任何地方使用这些sorting方法并获得代码重用。 这给了我一切可比的,再加上…所以我没有看到任何理由使用可比。
我会说:
- 如果比较直观,那么一定要用Comparable
- 如果你不清楚你的比较是否直观,那么使用一个比较器,因为它比较明确,因此对于需要维护代码的可怜的灵魂
- 如果有多个直观的比较可能,我更喜欢一个比较器,可能由类中的工厂方法build立比较。
- 如果比较是特殊用途,则使用比较器
Comparable – java.lang.Comparable: int compareTo(Object o1)
一个可比较的对象是能够比较自己与另一个对象。 类本身必须实现java.lang.Comparable接口,以便能够比较它的实例。
- 能够比较当前对象与提供的对象。
- 通过使用这个,我们可以
only one sort sequence
实现only one sort sequence
基于实例属性的only one sort sequence
。 EX:Person.id
- 一些预定义的类如String,Wrapper类,Date,Calendar等实现了Comparable接口。
Comparator – java.util.Comparator: int compare(Object o1, Object o2)
比较器对象能够比较两个不同的对象。 这个类不是比较它的实例,而是一些其他类的实例。 这个比较器类必须实现java.util.Comparator接口。
- 能够比较任何两个相同types的对象。
- 通过使用这个,我们可以根据实例属性实现
many sort sequence
和名称。 EX:Person.id, Person.name, Person.age
- 我们可以为我们的预定义的类实现定制sorting的Comparator接口。
例:
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) } }
- 对于自定义的sorting,我们去为比较@compare(o1,o2)为其他场景我们去比较@compareTo(o1),如果我们想要sorting多个字段,然后我们使用比较器不改变的代码。
对于Java 8 Lambda:Comparator请参考我的文章。
- 如果在编写这个类的时候,你只有一个用例,使用Comparable。
- 只有当你有不止一种分拣策略时才使用比较器。
这里也有类似的问题: class级什么时候应该是Comparable和/或Comparator?
我会说以下内容:实现类似自然顺序的东西比如,基于内部ID
如果你有一个比较复杂的比较algorithm,例如多个字段等等,就实现一个比较器。
如果您需要自然顺序sorting – 用户可比较如果您需要自定义顺序sorting – 使用比较器
例:
Class Employee{ private int id; private String name; private String department; }
自然顺序sorting将基于id,因为它是唯一的,自定义顺序sorting将是名称和部门。
Refrences:
什么时候应该是一个类比较和/或比较? http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html
可比:
每当我们只想存储同质元素和默认的自然sorting顺序时,我们可以去实现comparable
接口的类。
比较:
无论何时我们想要存储同类和异类元素,并且想要按默认的自定义sorting顺序sorting,我们可以去comparator
接口。
以下几点帮助您决定在哪种情况下应该使用Comparable,以及比较器:
1)代码可用性
2)单一与多个sorting标准
3)Arays.sort()和Collection.sort()
4)作为SortedMap和SortedSet中的键
5)更多类别与灵活性
6)组间比较
7)自然秩序
有关更详细的文章,您可以参考何时使用可比较和何时使用比较
非常简单的方法是假定所涉及的实体类在数据库中表示,然后在数据库表中需要由实体类的字段组成的索引? 如果答案是肯定的,则实施可比较的操作,并使用索引字段作为自然sorting顺序。 在所有其他情况下使用比较器。
我的需要是根据datesorting的。
所以,我使用了Comparable,它对我来说很简单。
public int compareTo(GoogleCalendarBean o) { // TODO Auto-generated method stub return eventdate.compareTo(o.getEventdate()); }
Comparable的一个限制是它们不能用于List以外的集合。
如果你拥有这个类,那么用Comparable吧 。 如果你不拥有这个类,但是你必须使用TreeSet或TreeMap,通常会使用Comparator,因为Comparator可以作为TreeSet或TreeMap的构造函数中的parameter passing。 您可以在http://preciselyconcise.com/java/collections/g_comparator.php中看到如何使用Comparator和Comparable
我曾经被要求在一次面试中sorting一定范围内的数字,比nlogn时间好。 (不使用计数sorting)
在对象上实现Comparable接口允许隐式sortingalgorithm使用重写的compareTo方法来sortingsorting元素,这将是线性时间。
用于实现Comparable
和Comparator
注释库:
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