何时使用比较器和比较器

发布于 2024-08-21 18:57:22 字数 371 浏览 4 评论 0原文

我有一个需要在字段上排序的对象列表,例如“分数”。没有多想,我编写了一个实现 Comparator 的新类,它完成了任务并且有效。

现在回过头来看,我想知道是否应该让我的类实现 Comparable,而不是创建一个实现 Comparator 的新类。分数是对对象进行排序的唯一字段。

  1. 我做了哪些可以接受的做法?

  2. 正确的方法是“首先让类实现 Comparable(为了自然排序),如果需要替代字段比较,然后创建一个实现 Comparator 的新类”吗?

  3. 如果上述(2)为真,那么是否意味着只有在类实现 Comparable 后才应该实现 Comparator? (假设我拥有原始类)。

I have a list of objects I need to sort on a field, say Score. Without giving much thought I wrote a new class that implements Comparator, that does the task and it works.

Now looking back at this, I am wondering if I should have instead have the my class implement Comparable instead of creating a new class that implements Comparator. The score is the only field that the objects will be ordered on.

  1. What I have done acceptable as a practice?

  2. Is the right approach "First have the class implement Comparable (for the natural ordering) and if an alternative field comparison is required, then create a new class that implements Comparator" ?

  3. If (2) above is true, then does it mean that one should implement Comparator only after they have the class implement Comparable? (Assuming I own the original class).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

陌上芳菲 2024-08-28 18:57:22

使用 Comparable 如果您想定义相关对象的默认(自然)排序行为,常见的做法是使用技术或自然(数据库?)标识符为此的对象。

使用 比较器如果您想定义外部可控排序行为,这可以覆盖默认排序行为。

另请参阅:

Use Comparable if you want to define a default (natural) ordering behaviour of the object in question, a common practice is to use a technical or natural (database?) identifier of the object for this.

Use Comparator if you want to define an external controllable ordering behaviour, this can override the default ordering behaviour.

See also:

擦肩而过的背影 2024-08-28 18:57:22

我想说,如果这是对类进行排序的清晰自然的方式,则对象应该实现 Comparable,并且任何需要对类进行排序的人通常都希望这样做。

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

换句话说,给定类名,是否清楚可比较的排序方式,或者您是否必须求助于阅读 javadoc?如果是后者,很可能未来的每个排序用例都需要一个比较器,此时可比较的实现可能会减慢该类用户的速度,而不是加快他们的速度。

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.

If, however, the sorting was an unusual use of the class, or the sorting only makes sense for a specific use case, then a Comparator is a better option.

Put another way, given the class name, is it clear how a comparable would sort, or do you have to resort to reading the javadoc? If it is the latter, odds are every future sorting use case would require a comparator, at which point the implementation of comparable may slow down users of the class, not speed them up.

半衾梦 2024-08-28 18:57:22

使用Comparable

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

使用 Comparator

  • 如果对象超出您的控制范围并且您无法使它们实现 Comparable
  • 当您想要比较与默认(由 Comparable 指定)行为不同的行为时。

Use Comparable:

  • if the object is in your control.
  • if the comparing behaviour is the main comparing behaviour.

Use Comparator :

  • if the object is outside your control and you cannot make them implement Comparable.
  • when you want comparing behaviour different from the default (which is specified by Comparable) behaviour.
她如夕阳 2024-08-28 18:57:22

可比较 - java.lang.Comparable: intcompareTo(Object o1)

可比较对象能够将自身与另一个对象进行比较。类本身必须实现 java.lang.Comparable 接口,以便能够比较其实例。

  • 能够将当前对象与提供的对象进行比较。
  • 通过使用它,我们可以根据实例属性实现仅一种排序序列
    EX: Person.id
  • 一些预定义类,如 String、Wrapper 类、Date、Calendar 已经实现了 Comparable 接口。

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

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

  • 能够比较任何两个相同类型的对象。
  • 通过使用它,我们可以实现许多排序序列并根据实例属性为每个排序序列命名。
    EX: Person.id, Person.name, Person.age
  • 我们可以为我们的预定义类实现 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)
    }
}
  • 对于自定义排序,我们使用比较器 @compare(o1, o2),对于其他场景,我们使用可比较的 @compareTo(o1),如果我们想要对多个字段进行排序,则无需更改代码,然后我们使用比较器。

对于 Java 8 Lambda:比较器,请参阅我的帖子。

Comparable - 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.

  • Capable of comparing current object with the provided object.
  • By using this we can implement only one sort sequence based on the instances properties.
    EX: Person.id
  • Some of the Predefined Classes like String, Wrapper classes, Date, Calendar has implemented Comparable interface.

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

A comparator object is capable of comparing two different objects. The class is not comparing its instances, but some other class’s instances. This comparator class must implement the java.util.Comparator interface.

  • Capable of comparing any two Objects of Same Type.
  • By using this we can implement many sort sequence and name each, based on the instances properties.
    EX: Person.id, Person.name, Person.age
  • We can implement Comparator interface to our Pre-defined classes for Customized sorting.

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)
    }
}
  • For customized sorting we go for comparator @compare(o1, o2) for other scenarios we go for comparable @compareTo(o1), with out changing code if we want to sort more than one field then we use comparator.

For Java 8 Lambda : Comparator refer to my post.

滥情哥ㄟ 2024-08-28 18:57:22

如果需要根据自然顺序对对象进行排序,则使用 Comparable,而如果需要根据不同对象的属性进行排序,则使用 Java 中的 Comparator。

Comparable 和 Comparator 之间的主要区别:

+------------------------------------------------------------------------------------+
¦               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.        ¦
+------------------------------------------------------------------------------------+

If sorting of objects needs to be based on natural order then use Comparable whereas if your sorting needs to be done on attributes of different objects, then use Comparator in Java.

Main differences between Comparable and Comparator:

+------------------------------------------------------------------------------------+
¦               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.        ¦
+------------------------------------------------------------------------------------+
呆萌少年 2024-08-28 18:57:22

当您比较同一类的实例时,应该使用 Comparable。

比较器可用于比较不同类的实例。

Comparable 是由需要为其对象定义自然顺序的类实现的。
例如,String 实现了 Comparable。

如果需要不同的排序顺序,则实现比较器并定义其自己的比较两个实例的方式。

Comparable should be used when you compare instances of the same 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.
For example, String implements Comparable.

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

笑看君怀她人 2024-08-28 18:57:22

比较器可以完成同类功能的所有功能,甚至更多。

<代码>| |类似|比较器
._____________________________________________________________________________
用于允许 Collections.sort 工作 |是的 |是的
可以比较多个字段 |是的 |是的
住在您正在比较并服务的班级内 | |
作为“默认”比较方式 |是的 |是的
可以住在您所比较的班级之外 |没有|是的
可以有多个具有不同方法名称的实例 |没有|是的
输入参数可以是 | 的列表只是对象|任何类型
可以使用枚举 |没有|是的

我找到了将比较器用作匿名类的最佳方法,如下所示:

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());
        }
    });
}

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

  • sortAccountsByPriority
  • sortAccountsByType
  • sortAccountsByPriorityAndType

    etc...

现在,您可以在任何地方使用这些排序方法并实现代码重用。
这给了我所有可比较的东西,再加上更多......所以我根本不认为有任何理由使用可比较的东西。

Comparator does everything that comparable does, plus more.

| | 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

I found the best approach to use comparators as anonymous classes as follows:

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());
        }
    });
}

You can create multiple versions of such methods right inside the class you’re planning to sort. So you can have:

  • sortAccountsByPriority
  • sortAccountsByType
  • sortAccountsByPriorityAndType

    etc...

Now, you can use these sort methods anywhere and get code reuse.
This gives me everything a comparable would, plus more ... so I don’t see any reason to use comparable at all.

﹎☆浅夏丿初晴 2024-08-28 18:57:22

我想说:

  • 如果比较是直观的,那么一定要实现 Comparable
  • 如果不清楚你的比较是否直观,请使用比较器,因为它更
    明确的,因此对于必须维护代码的可怜的灵魂来说更清楚,
  • 如果可能有多个直观的比较,我更喜欢一个比较器,
    可能是通过要比较的类中的工厂方法构建的。
  • 如果比较有特殊目的,则使用Comparator

I would say:

  • if the comparison is intuitive, then by all means implement Comparable
  • if it is unclear wether your comparison is intuitive, use a Comparator as it's more
    explicit and thus more clear for the poor soul who has to maintain the code
  • if there is more than one intuitive comparison possible I'd prefer a Comparator,
    possibly build by a factory method in the class to be compared.
  • if the comparison is special purpose, use Comparator
花辞树 2024-08-28 18:57:22

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

1) 代码可用性

2) 单个与多个排序标准

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

4) 作为 SortedMap 和 Collection 中的键SortedSet

5) 更多类数与灵活性

6) 类间比较

7) 自然顺序

有关更详细的文章,您可以参考 何时使用比较器以及何时使用比较器

The following points help you in deciding in which situations one should use Comparable and in which Comparator:

1) Code Availabilty

2) Single Versus Multiple Sorting Criteria

3) Arays.sort() and Collection.sort()

4) As keys in SortedMap and SortedSet

5) More Number of classes Versus flexibility

6) Interclass comparisions

7) Natural Order

For more detailed article you can refer When to use comparable and when to use comparator

独木成林 2024-08-28 18:57:22

如果你需要自然顺序排序——User Comparable
如果您需要自定义顺序排序 - 使用比较器

示例:

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

自然顺序排序将基于 ID,因为它是唯一的,而自定义顺序排序将是名称和部门。

参考资料:
什么时候类应该是 Comparable 和/或 Comparator?< /a>
http://javarevisited.blogspot.com/2011/ 06/comparator-and-comparable-in-java.html

If you need natural order sorting -- User Comparable
IF you need Custom Order Sorting - Use Comparator

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.

Refrences:
When should a class be Comparable and/or Comparator?
http://javarevisited.blogspot.com/2011/06/comparator-and-comparable-in-java.html

反差帅 2024-08-28 18:57:22
  • 如果在写课程的时候
    您只有一个排序用例
    使用比较。
  • 仅当您拥有多个时
    排序策略实施a
    比较器。
  • If at the moment of writing the class
    you have only one use case of sorting
    use Comparable.
  • Only when you have more than one
    strategy of sorting implement a
    Comparator.
东北女汉子 2024-08-28 18:57:22

这里有一个类似的问题:何时应该一个类是可比较的和/或比较器?

我会说以下内容:
为自然排序之类的东西实现 Comparable,例如基于内部 ID。

如果您有更复杂的比较算法(例如多个字段等),则实现 Comparator。

There had been a similar question here: When should a class be Comparable and/or Comparator?

I would say the following:
Implement Comparable for something like a natural ordering, e.g. based on an internal ID

Implement a Comparator if you have a more complex comparing algorithm, e.g. multiple fields and so on.

晨与橙与城 2024-08-28 18:57:22

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

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

Comparable:
Whenever we want to store only homogeneous elements and default natural sorting order required, we can go for class implementing comparable interface.

Comparator:
Whenever we want to store homogeneous and heterogeneous elements and we want to sort in default customized sorting order, we can go for comparator interface.

情深缘浅 2024-08-28 18:57:22

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

所以,我使用了 Comparable,它对我来说很容易工作。

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

Comparable 的一项限制是它们不能用于除 List 之外的 Collections。

My need was sort based on date.

So, I used Comparable and it worked easily for me.

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

One restriction with Comparable is that they cannot used for Collections other than List.

山川志 2024-08-28 18:57:22

如果您拥有该课程,最好选择可比较。通常,如果您不拥有该类,则使用 Comparator,但必须将其使用 TreeSetTreeMap,因为 Comparator 可以作为参数传递TreeSet 或 TreeMap 的构造函数。您可以在 http://preciselyconcise.com/java/collections/g_comparator 中了解如何使用 Comparator 和 Comparable .php

If you own the class better go with Comparable. Generally Comparator is used if you dont own the class but you have to use it a TreeSet or TreeMap because Comparator can be passed as a parameter in the conctructor of TreeSet or TreeMap. You can see how to use Comparator and Comparable in http://preciselyconcise.com/java/collections/g_comparator.php

懵少女 2024-08-28 18:57:22

在一次采访中,我被要求在比 nlogn 更好的时间内对一定范围的数字进行排序。 (不使用计数排序)

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

I have been asked sorting of a definite range of numbers in better than nlogn time in one of interview. (Not using Counting sort)

Implementing Comparable interface over an object allows implicit sorting algos to use overridden compareTo method to order sort elements and that would be linear time.

南笙 2024-08-28 18:57:22

Comparable 是默认的自然排序顺序,数值按升序排列,字符串按字母顺序排列。
例如:

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

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

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]

Comparable is the default natural sorting order provided for numerical values are ascending and for strings are alphabetical order.
for eg:

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

Comparator is the custom sorting order implemented in custom myComparator class by overriding a compare method
for eg:

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]
狂之美人 2024-08-28 18:57:22

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

Very simple approach is to assume that the entity class in question be represented in database and then in database table would you need index made up of fields of entity class? If answer is yes then implement comparable and use the index field(s) for natural sorting order. In all other cases use comparator.

把人绕傻吧 2024-08-28 18:57:22

我的用于实现 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

My annotation lib for implementing Comparable and 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);         
    }  
}

Click the link to see more examples.
http://code.google.com/p/compamatic/wiki/CompamaticByExamples

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文