Collections.sort 多个条件

Collections.sort for multiple conditions

我有一个要排序的对象列表。但是我有三个不同的条件。这就是为什么我有这个代码:

Collections.sort(myList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject o1, MyObject o2) {
        // my code
    }
});

三次。首先将条件为 x 的所有元素排序到列表底部。然后第二次将条件为 y 的所有元素排序到底部,再次对条件为 z.

现在我想知道如何在一个比较方法中组合多个条件。所以我不必这样做三次。

编辑: 条件更清楚。我想将所有符合条件 x 的对象排序到列表底部。如果一个元素满足标准 y,它甚至应该低于 x,同样适用于 z.

的模拟

您可以使用 Java 流。使用 Collection.sort():

时也会用到这个
myList.sort(Comparator.comparing(MyObject::getAttributeX)
    .thenComparing(i -> i.getSomething().getSubValue())
    .thenComparing((a, b) -> a.getInt() - b.getInt()));

如果您使用的版本低于 Java 8,您必须自己在 Comparator 中实现排序逻辑或使用外部库:

Collections.sort(myList, new Comparator<MyObject>() {
    @Override
    public int compare(MyObject a, MyObject b) {
        int cmp0 = a.getAttributeX().compareTo(b.getAttributeX());
        if (cmp0 != 0) {
            return cmp0;
        }
        int cmp1 = a.getSomething().getSubValue().compareTo(b.getSomething().getSubValue());
        if (cmp1 != 0) {
            return cmp1;
        }
        return a.getInt() - b.getInt();
    }
});

您可以使用比较链,例如:

   public int compareTo(Foo that) {
     return ComparisonChain.start()
         .compare(this.aString, that.aString)
         .compare(this.anInt, that.anInt)
         .compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
         .result();
   }

看这里:link to docs

我假设 MyObject 有类似

的方法
public boolean isX() {
    return // either false or true;
}

那么这样排序最简单:

    Collections.sort(myList,
            Comparator.comparing(MyObject::isX)
                    .thenComparing(MyObject::isY)
                    .thenComparing(MyObject::isZ));

由于 isX 等 return boolean 值,这些值被排序,false 排在 true 之前。因此,排序将确保满足 x 条件(isX returns true)的所有对象都将出现在列表的末尾。在剩余的对象中,那些满足 y 的对象将最后移动,就在 x-s 之前。同样对于 z.

如果 x、y 和 z 是由进行排序的 class 中的方法确定的怎么办?在这个例子中我们称它为 Sorter class。这些方法可能如下所示:

public static boolean isY(MyObject obj) {
    return // either false or true;
}

您只需将 MyObject::isX 替换为 Sorter::isX:

    Collections.sort(myList,
            Comparator.comparing(Sorter::isX)
                    .thenComparing(Sorter::isY)
                    .thenComparing(Sorter::isZ));

你也可以混用,在Sorter中定义一些方法,在MyMethod中定义一些方法。

真正发生的是 boolean 值 return 装箱到 Boolean 对象中,然后进行比较,但您不必关心这个细节。

编辑: 较低 Android API 级别的版本:

    Comparator<MyObject> xyzComparator = new Comparator<MyObject>() {

        @Override
        public int compare(MyObject o1, MyObject o2) {
            int diff = Boolean.compare(o1.isX(), o2.isX());
            if (diff != 0) {
                return diff;
            }
            diff = Boolean.compare(o1.isY(), o2.isY());
            if (diff != 0) {
                return diff;
            }
            diff = Boolean.compare(o1.isZ(), o2.isZ());
            // return whether 0 or not
            return diff;
        }
    };
    Collections.sort(myList, xyzComparator);

它甚至省去了上面提到的自动装箱。