JiK*_*Kra 5 java sorting java-8 java-stream
我有以下代码段:
List<O> os = new ArrayList<>();
os.add(new O("A", 3, "x"));
os.add(new O("A", 2, "y"));
os.add(new O("B", 1, "z"));
Comparator<O> byA = Comparator.comparing(O::getA);
Comparator<O> byB = Comparator.comparing(O::getB);
// I want to use rather this...
List<Comparator<O>> comparators = new ArrayList<>();
comparators.add(byA);
comparators.add(byB);
os.stream()
.sorted(byB.thenComparing(byA))
.forEach(o -> System.out.println(o.getC()));
Run Code Online (Sandbox Code Playgroud)
如您所见,我使用显式两个比较器进行排序.但是如果我在某个列表中有未知数量的比较器并且我想按它们排序呢?有什么办法吗?或者应该使用旧时尚方式比较器与多个ifs?
Grz*_*rek 15
如果列表或任何其他集合中有多个比较器,则可以通过执行以下操作的缩减来替换它们Stream:
List<Comparator<String>> comparators = ...
Comparator<String> combined = comparators.stream()
.reduce(Comparator::thenComparing)
.orElse(someDefaultComparator); // empty list case
Run Code Online (Sandbox Code Playgroud)
所有实例将thenComparing根据输入列表中的顺序一起组合.
通过使用简单的for循环,使用非流方法可以实现相同的目的:
Comparator<String> result = comparators.get(0);
for (int i = 1; i < comparators.size(); i++) {
result = result.thenComparing(comparators.get(i));
}
Run Code Online (Sandbox Code Playgroud)
reduce通过.thenComparing()在迭代中调用累加的比较器和电流比较器,可以将比较器流传输到单个比较器:
Optional<Comparator<O>> comparator = Optional.ofNullable(comparators.stream()
.reduce(null, (acc, current) -> acc == null ? current : acc.thenComparing(current), (a, b) -> a));
os.stream()
.sorted(comparator.orElse((a,b) -> 0))
.forEach(o -> System.out.println(o.getC()));
Run Code Online (Sandbox Code Playgroud)
在这个例子中,我使用Optional<Comparator<O>>和包装缩小结果Optional.ofNullable()来处理具有空比较器列表的情况.然后,您可以决定何时将结果传递给sorted()方法,以便在空列表的情况下执行操作 - 您可以使用(a,b)->0不对任何内容进行排序的比较器.
那么你想要应用多少比较器并不重要.但是有一个但是 - 在给定的收集问题上比较器的顺序.在给定的示例中,我按升序应用比较器(从列表的第一个元素开始到最后一个元素).它会严重影响排序结果.
例如,在您的示例中,您可以调用byB.thenComparing(byA).然后产生不同的结果byA.thenComparing(byB).我可以假设在某些情况下你想控制比较器的应用顺序.
现场演示: