具有多个字段的对象的 Java 比较器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23981199/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 09:31:40  来源:igfitidea点击:

Java Comparator for Objects with multiple fields

javasortingobjectcomparator

提问by Tapas Bose

I have an Object Collectionwith 5 fields:

我有一个Collection包含 5 个字段的对象:

id;
entityType;
entityId;
brandId;
productId;

To sort an ArrayListof CollectionI have written the following Comparaor.

为了排序ArrayListCollection我写了以下内容Comparaor

Comparator<Collection> collectionComparator = new Comparator<Collection>() {

    @Override
    public int compare(Collection collection1, Collection collection2) {
        if(collection1.getId().equals(collection2.getId())) {
            if(collection1.getEntityType().equals(collection2.getEntityType())) {
                if(collection1.getEntityId().equals(collection2.getEntityId())) {
                    if(collection1.getBrandId().equals(collection2.getBrandId())) {
                        return collection1.getProductId().compareTo(collection2.getProductId());
                    } else {
                        return collection1.getBrandId().compareTo(collection2.getBrandId());
                    }
                } else {
                    return collection1.getEntityId().compareTo(collection2.getEntityId());
                }
            } else {
                return collection1.getEntityType().compareTo(collection2.getEntityType());
            }
        } 

        return collection1.getId().compareTo(collection2.getId());
    }
};

Is this the right way to implement Comparatoron the object which has multiple fields to compare?

这是Comparator在具有多个字段进行比较的对象上实现的正确方法吗?

采纳答案by MikeFHay

Your method might be correct, but it is inefficient (unnecessarily calls equals) and difficult to read. It could be rewritten something like this:

您的方法可能是正确的,但效率低下(不必要地调用 equals)并且难以阅读。可以这样改写:

public int compare(Collection c1, Collection c2)
{
    int n;
    n = c1.id.compareTo(c2.id);
    if (n != 0) return n;
    n = c1.entityType.compareTo(c2.entityType);
    if (n != 0) return n;
    n = c1.brandId.compareTo(c2.brandId);
    if (n != 0) return n;
    return c1.productId.compareTo(c2.productId);
}

Even better is to use a library method which abstracts all this logic away so you don't have to think about it. E.g. using apache.commons.lang CompareToBuilder

更好的是使用一个库方法来抽象所有这些逻辑,这样你就不必考虑它了。例如使用apache.commons.lang CompareToBuilder

public int compare(Collection c1, Collection c2)
{
    return new CompareToBuilder()
            .append(c1.id, c2.id)
            .append(c1.entityType, c2.entityType)
            .append(c1.brandId, c2.brandId)
            .append(c1.productId, c2.productId)
            .toComparison();
}

回答by kajacx

First, Collectionis a class from java.utilpackage, so it's probably not the best idea to name your own class Collectiontoo, although it is certainly possible.

首先,Collection是一个来自java.util包的类,所以命名你自己的类可能不是最好的主意Collection,尽管这当然是可能的。

Second, JDK8 have some neat ways to create comparators, check here: jdk8 comparators

其次,JDK8 有一些巧妙的方法来创建比较器,请查看这里:jdk8比较器

Esspecially section 6 and 9.

特别是第 6 和 9 节。

EDIT: Without JKD8:

编辑:没有 JKD8:

When comparing by 5 different attributes, I wouldn't hardcode the comparasion like that, you can always create your own comparator chainer (something like point 9 from previous link) and chain 5 separate comparators together.

当通过 5 个不同的属性进行比较时,我不会像这样对比较进行硬编码,您始终可以创建自己的比较器链接器(类似于上一个链接中的第 9 点)并将 5 个单独的比较器链接在一起。