java - 是否可以使用 Comparator.comparingInt 链按两个字段以相反的自然顺序对对象进行排序

标签 java java-8 reverse comparator method-chaining

假设我想以相反的顺序对字段 height 上的 ArrayList 中的对象进行排序,如果两个值相同,我想进一步对字段宽度进行排序也以相反的顺序。 有没有办法使用类似

的东西
 Comparator<Test> comparator = Comparator
            .comparingInt((Test t) -> t.height).reversed()
            .thenComparingInt((Test t ) -> t.width).reversed();

我知道我可以使用类似的东西:

Collections.sort(list, new Comparator<Test>() {

        public int compare(Test o1, Test o2) {

            Integer x1 =  o1.height;
            Integer x2 =  o2.height;
            int sComp = x2.compareTo(x1);

            if (sComp != 0) {
                return sComp;
            }

            x1 = o1.width;
            x2 = o2.width;
            return x2.compareTo(x1);
        }});

但是我真的很好奇是否有一条线解决方案

所以关于这个小例子

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        Test one = new Test();
        one.height = 2;
        one.width = 1;
        Test two = new Test();
        two.height = 2;
        two.width = 3;
        Test three = new Test();
        three.height = 1;
        three.width = 1;

        Comparator<Test> comparator = Comparator
            .comparingInt((Test t) -> t.height).reversed()
            .thenComparingInt((Test t ) -> t.width).reversed();

        List<Test> list = new ArrayList<>();
        list.add(one);
        list.add(two);
        list.add(three);

        list.stream()
            .sorted(comparator)
            .forEach(e -> System.out.println(e.height + "/" + e.width));
    }
}

class Test {
    int width;
    int height;
}

我得到输出:

1/1
2/3
2/1

因为第二个 reversed() 反转了整个列表。 有没有办法生成以下输出:

2/3
2/1
1/1

最佳答案

只需从 comparingInt 中删除 reversed() 并仅在 thenComparingLong 上调用 reversed:

Comparator<Test> comparator = 
      Comparator.comparingInt((Test t) -> t.height) // <--- removed reverse from this comparator
                .thenComparingLong((Test t ) -> t.width).reversed();

此外,鉴于 width 是一个 int,我将使用 thenComparingInt 而不是 thenComparingLong

此外,关于流管道,我建议使用 forEachOrdered,因为您关心元素打印的顺序

forEach 记录为:

The behavior of this operation is explicitly nondeterministic. For parallel stream pipelines, this operation does not guarantee to respect the encounter order of the stream, as doing so would sacrifice the benefit of parallelism.

因此:

 list.stream()
     .sorted(comparator)
     .forEachOrdered(e -> System.out.println(e.height + "/" + e.width));

关于java - 是否可以使用 Comparator.comparingInt 链按两个字段以相反的自然顺序对对象进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54046767/

相关文章:

Java mapToInt 与 Reduce with map

Java 8 从 CSV 流过滤行但保留第一行

python - 如何就地反转 NumPy 数组?

python - 为什么这个 "[::-1]"在 Python 中返回一个反向列表?

java - 如何在数组中打印 [ ] (Java)

java - 如何获取 Jersey JaxRS 中的所有查询参数?

java - 方法 : java. lang.String.getCatalogName() 的签名不适用于参数

java - HttpPost -> 重定向 -> 需要响应的位置或正文

java - 我可以使用正则表达式来查找java中类的方法吗?

java - 如何使用 lambda 编写新的 ListChangeListener<Item>()?