简体   繁体   English

决定使用可比或比较器

[英]Deciding to use Comparable or Comparator

My program implements a Product class whose objects contain the following instance variables: name , priority , price , and amount . 我的程序实现了一个Product类,其对象包含以下实例变量: nameprioritypriceamount

I have a LinkedList of Product objects that I need to sort before doing any other operations on the LinkedList . 我有一个LinkedListProduct ,我需要在做任何其他操作之前进行排序对象LinkedList

I want to sort the list first by priority (from lowest to highest). 我想按优先顺序(从最低到最高)对列表进行排序。 If priority is the same, then look at the price (lowest to highest), then the name (alphabetical order). 如果优先级相同,则查看价格(从最低到最高),然后查看名称(字母顺序)。

I have done a lot of reading about Collections.sort , Comparable , and Comparator . 我已经阅读了很多有关Collections.sortComparableComparator I believe I need to use the Comparable interface and implement a compareTo method. 我相信我需要使用Comparable接口并实现compareTo方法。 My thinking is that because both priority , price , and name have a "natural" ordering it makes more sense to use Comparable . 我的想法是,因为prioritypricename都具有“自然”的顺序,所以使用Comparable更有意义。

public class Product extends ProductBase implements PrintInterface, Comparable<Product>{
    private String name;
    private int priority; 
    private int cents;
    private int quantity;

    // setters and getters

    /**
    * Compare current Product object with compareToThis
    * return 0 if priority, price and name are the same for both  
    * return -1 if current Product is less than compareToThis
    * return 1 if current Product is greater than compareToThis
    */ 

    @override
    public int compareTo(Product compareToThis)
}

Then when I want to sort my LinkedList I just call Collections.sort(LinkedList) . 然后,当我想对LinkedList进行排序时,只需调用Collections.sort(LinkedList) Before I start writing the code, can you tell me if I am I missing or forgetting anything? 在我开始编写代码之前,您能告诉我我是否想念还是忘记了什么吗?

** * ** * ** * **** UPDATE * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** * **** 更新 * ** * ** * ** * ** * ** * ** * ** * ** * ** * ** *

I just created a separate class called ProductComparator with a compare method. 我刚刚使用compare方法创建了一个单独的类ProductComparator。

This is part of the LinkedList class.. 这是LinkedList类的一部分。

import java.util.Collections;

public class LinkedList {

private ListNode head; 

public LinkedList() { 
    head = null;
}
     // this method will sort the LinkedList using a ProductComparator
public void sortList() {
    ListNode position = head;
    if (position != null) {
        Collections.sort(this, new ProductComparator());
    }
}
// ListNode inner class
private class ListNode {

    private Product item;
    private ListNode link;

    // constructor
    public ListNode(Product newItem, ListNode newLink) {
        item= newItem;
        link = newLink;
    }
}

} }

I am getting the following error from the IDE when I compile. 编译时,我从IDE中收到以下错误。

The method sort(List, Comparator) in the type Collections is not applicable for the arguments (LinkedList, ProductComparator). 类型Collections中的方法sort(List,Comparator)不适用于参数(LinkedList,ProductComparator)。

Does anyone know why I am getting this error and can point me in the right direction to resolve it? 有谁知道为什么我会收到此错误,并且可以指出正确的方向来解决它?

If there is a "natural" ordering, use Comparable. 如果存在“自然”排序,请使用Comparable。 Rule of thumb for figuring out if the ordering is "natural" is, whether the order of the objects will always be that. 确定排序是否为“自然”的经验法则是,对象的顺序是否始终是这样。

Having said that, the decision whether to use Comparable or Camparator is not the kind of decision you need to think too much about. 话虽如此,决定使用Comparable还是Camparator并不是您需要考虑太多的决定。 Most IDEs have refactoring tools which makes the conversion between a Comparable and a Comparator very easy. 大多数IDE都有重构工具,这些工具使Comparable和Comparator之间的转换非常容易。 So if you choose to walk the wrong path now, changing that will not require too much effort. 因此,如果您现在选择走错误的道路,那么进行更改将不需要太多的努力。

The order you define here on your Product is very specific and 您在产品上定义的订单非常具体,

  • will probably change in future versions of your program 可能会在程序的将来版本中发生变化
  • might be enriched with contextual parameterization 可能会因上下文参数化而丰富
  • won't cover new features 不会涵盖新功能

So it can hardly been said "natural". 因此,很难说它是“自然的”。

I'd suggest to define a constant, for example 我建议定义一个常量,例如

public static Comparator<Product> STANDARD_COMPARATOR = new Comparator<Product>() {
    public int compare(Product p1, Product p1) {
        return ...
    }
};

then you'll be able to easily sort anywhere with 那么您将可以轻松地在任何地方进行排序

Collections.sort(myProductList, Product.STANDARD_COMPARATOR);

Your code will evolve in a better manner as you'll add other comparators. 当您添加其他比较器时,您的代码将以更好的方式发展。

Just like you should generally prefer composition over inheritance, you should try to avoid defining the behavior of your objects in immutable manner. 就像您通常应该更喜欢合成而不是继承一样,您应该尝试避免以不可变的方式定义对象的行为。

If your order was based only on numbers, Comparable would be fine. 如果您的订单仅基于数字,那么“可Comparable就可以了。

However, since your order (sometimes) involves lexical order of text, a Comparator class is better, since use of Comparable would mean using String.compareTo which would prevent you from having internationalization. 但是,由于您的顺序(有时)涉及文本的词法顺序,因此Comparator类更好,因为使用Comparable意味着使用String.compareTo会阻止您进行国际化。

A separate class which implements Comparator can make use of a localized Collator for comparing Strings. 实现Comparator单独类可以利用本地化的Collator来比较String。 For instance: 例如:

public class ProductComparator
implements Comparator<Product> {
    private final Collator collator;

    public ProductComparator() {
        this(Locale.getDefault());
    }

    public ProductComparator(Locale locale) {
        this.collator = Collator.getInstance(locale);
    }

    public int compare(Product product1,
                       Product product2) {

        int c = product1.getPriority() - product2.getPriority();
        if (c == 0) {
            c = product1.getPrice() - product2.getPrice();
        }
        if (c == 0) {
            c = collator.compare(product1.getName(), product2.getName());
        }
        return c;
    }
}

Regardless of whether you go with Comparable or Comparator, it is wise to make sure Product has an equals method which checks the same attributes as the comparison code. 无论您使用Comparable还是Comparator,明智的做法是确保Product具有一个equals方法,该方法检查与比较代码相同的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM