当你在之后链接一个操作时,实现将利用数据的排序性质并避免构建内部,这可以通过以下程序来演示distinct()
sorted()
HashSet
public class DistinctAndSort {
static int COMPARE, EQUALS, HASHCODE;
static class Tracker implements Comparable<Tracker> {
static int SERIAL;
int id;
Tracker() {
id=SERIAL++/2;
}
public int compareTo(Tracker o) {
COMPARE++;
return Integer.compare(id, o.id);
}
public int hashCode() {
HASHCODE++;
return id;
}
public boolean equals(Object obj) {
EQUALS++;
return super.equals(obj);
}
}
public static void main(String[] args) {
System.out.println("adjacent sorted() and distinct()");
Stream.generate(Tracker::new).limit(100)
.sorted().distinct()
.forEachOrdered(o -> {});
System.out.printf("compareTo: %d, EQUALS: %d, HASHCODE: %d%n",
COMPARE, EQUALS, HASHCODE);
COMPARE=EQUALS=HASHCODE=0;
System.out.println("now with intermediate operation");
Stream.generate(Tracker::new).limit(100)
.sorted().map(x -> x).distinct()
.forEachOrdered(o -> {});
System.out.printf("compareTo: %d, EQUALS: %d, HASHCODE: %d%n",
COMPARE, EQUALS, HASHCODE);
}
}
这将打印
adjacent sorted() and distinct()
compareTo: 99, EQUALS: 99, HASHCODE: 0
now with intermediate operation
compareTo: 99, EQUALS: 100, HASHCODE: 200
中间操作(简单如 )无法被实现识别,因此,它必须假设元素可能不会根据映射函数的结果进行排序。map(x -> x)
Stream
不能保证会发生这种优化,但是,可以合理地假设 Stream 实现的开发人员不会删除该优化,甚至不会尝试添加更多优化,因此滚动自己的实现将阻止您的代码从未来的优化中受益。
此外,您创建的是“有状态谓词”,强烈建议不要这样做,当然,在与并行流一起使用时会中断。
如果您不相信流 API 能够足够高效地执行此操作,则最好在没有流 API 的情况下实现此特定操作。