如果使用自定义 Comparator 创建为 SortedMap 生成的流的流特征,则可能无法排序

2022-01-22 00:00:00 java-8 java java-stream

Mastering Lambdas 作者 Maurice Naftalin,第 6 章 - 流性能.

Mastering Lambdas by Maurice Naftalin, Ch6 - Stream Performance.

有关于流在不同执行阶段(中间和终端)的不同特征的解释.例如.

There is explanation about the different characteristics of streams at the different stages of execution(intermediate & terminal). For eg.

Stream.of(8,3,5,6,7,4)//ORDERED, SIZED
.filer(i->i%2==0) // ORDERED
.sorted() // ORDERED, SORTED
.distinct() // DISTINCT, ORDERED, SORTED
.map(i->i+1) // ORDERED
.unordered(); //none

让我感到困惑的是对 SORTED 特征的解释:

What was confusing to me was explanation of SORTED characteristics :

如果 Comparator 已定义并用于此目的,则流元素可能已按其他顺序排序,但此类流不具有 SORTED 特性."

为什么如果为实现排序数据结构(在上述情况下为排序映射)提供自定义比较器,框架不会考虑创建具有排序特征的流?

Why if the custom comparator is provided for the implementation of Sorted Data Structure(SortedMap in above case) the framework would not consider creating streams with SORTED characteristic?

推荐答案

Flown 在他的评论中是绝对正确的.SORTED 仅针对自然顺序进行报告,并且之前已对此进行过辩论.首先,这甚至在内部用作名为:isNaturalSort:

Flown is absolutely correct in his comment. SORTED is only reported for natural order and this has been debated before. First this is even internally used as a flag called: isNaturalSort:

/**
     * Sort using natural order of {@literal <T>} which must be
     * {@code Comparable}.
     */
    OfRef(AbstractPipeline<?, T, ?> upstream) {
        super(upstream, StreamShape.REFERENCE,
              StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SORTED);
        this.isNaturalSort = true;

通过 sorted(CustomComparator) 使用时,相同的标志 isNaturalSort 设置为 false.

The same flag isNaturalSort is set to false when used via sorted(CustomComparator).

这是内部细节,jdk 开发人员似乎没有发现这样实现它有用 - 可能与它没有任何关系,可能真的有用.但这可能会改变......

This is an internal details and it seems that the jdk developers did not find useful to implemented it as such - there was probably nothing to do with it that could be really useful. But this might change...

这里至少还有一个缺陷.想象这样一个类:

There is at least one flaw here still. Imagine a class like this:

static class User implements Comparable<User> {
    private final int id;

    public User(int id) {
        super();
        this.id = id;
    }

    public int getId() {
        return id;
    }

    @Override
    public int compareTo(User usr) {
        return 42; // don't do this
    }

}

还有一些流操作:

Stream<User> byId = Stream.of(new User(12), new User(10))
            .sorted(Comparator.comparing(User::getId));

System.out.println(byId.spliterator().hasCharacteristics(Spliterator.SORTED));

Stream<User> natural = Stream.of(new User(12), new User(10))
            .sorted(Comparator.naturalOrder());

System.out.println(natural.spliterator().hasCharacteristics(Spliterator.SORTED)); 

Stream<User> plain = Stream.of(new User(12), new User(10)).sorted();
System.out.println(plain.spliterator().hasCharacteristics(Spliterator.SORTED));

前两个报false,最后一个报true;这至少很奇怪.

The first two report false, but the last one reports true; which is at least weird.

相关文章