java8新特性-引用流-sorted
Stream的执行流程参考https://www.cnblogs.com/shigongp/p/17181380.html。
例子:
List<User> users = new ArrayList<>();
users.add(new User("张三",30));
users.add(new User("李四",34));
users.add(new User("王五",20));
System.out.println(users);
List<User> collect = users.stream().sorted(Comparator.comparing(User::getAge)).collect(Collectors.toList());
System.out.println(collect);
上面的例子是按照age字段对List
源码分析
ReferencePipeline#sorted(Comparator<? super P_OUT> comparator)
public final Stream<P_OUT> sorted(Comparator<? super P_OUT> comparator) {
return SortedOps.makeRef(this, comparator);
}
SortedOps#makeRef
static <T> Stream<T> makeRef(AbstractPipeline<?, T, ?> upstream,
Comparator<? super T> comparator) {
return new OfRef<>(upstream, comparator);
}
关注SortedOps#OfRef#opWrapSink方法
SortedOps#OfRef#opWrapSink
@Override
public Sink<T> opWrapSink(int flags, Sink<T> sink) {
Objects.requireNonNull(sink);
// If the input is already naturally sorted and this operation
// also naturally sorted then this is a no-op
if (StreamOpFlag.SORTED.isKnown(flags) && isNaturalSort)
return sink;
else if (StreamOpFlag.SIZED.isKnown(flags))
return new SizedRefSortingSink<>(sink, comparator);
else
return new RefSortingSink<>(sink, comparator);
}
如果Stream是SORTED,即Stream已经有序直接返回。如果Stream有SIZED标志,表示Stream中元素数量有限,返回SizedRefSortingSink,否则返回RefSortingSink。上面的例子返回SizedRefSortingSink。
SizedRefSortingSink#begin
public void begin(long size) {
if (size >= Nodes.MAX_ARRAY_SIZE)
throw new IllegalArgumentException(Nodes.BAD_SIZE);
array = (T[]) new Object[(int) size];
}
创建了Object[]数组。此时并没有调用downstream.begin。
SizedRefSortingSink#accept
public void accept(T t) {
array[offset++] = t;
}
将元素加到数组中。
SizedRefSortingSink#end
public void end() {
Arrays.sort(array, 0, offset, comparator);
downstream.begin(offset);
if (!cancellationWasRequested) {
for (int i = 0; i < offset; i++)
downstream.accept(array[i]);
}
else {
for (int i = 0; i < offset && !downstream.cancellationRequested(); i++)
downstream.accept(array[i]);
}
downstream.end();
array = null;
}
调用Arrays.sort对数组排序后,调用downstream.begin将Stream操作向下传播。for循环对每个排序后的元素调用downstream.accept,交由下一个操作处理。之后调用downstream.end()结束处理。
如果调用的是sorted()函数:
ReferencePipeline#sorted()
public final Stream<P_OUT> sorted() {
return SortedOps.makeRef(this);
}
进入SortedOps.makeRef并向下追踪可看到最终调用:
OfRef(AbstractPipeline<?, T, ?> upstream) {
super(upstream, StreamShape.REFERENCE,
StreamOpFlag.IS_ORDERED | StreamOpFlag.IS_SORTED);
this.isNaturalSort = true;
// Will throw CCE when we try to sort if T is not Comparable
@SuppressWarnings("unchecked")
Comparator<? super T> comp = (Comparator<? super T>) Comparator.naturalOrder();
this.comparator = comp;
}
可看到comparator是Comparator.naturalOrder()。
抛开这个例子不谈,看下RefSortingSink:
private static final class RefSortingSink<T> extends AbstractRefSortingSink<T> {
private ArrayList<T> list;
RefSortingSink(Sink<? super T> sink, Comparator<? super T> comparator) {
super(sink, comparator);
}
@Override
public void begin(long size) {
if (size >= Nodes.MAX_ARRAY_SIZE)
throw new IllegalArgumentException(Nodes.BAD_SIZE);
list = (size >= 0) ? new ArrayList<T>((int) size) : new ArrayList<T>();
}
@Override
public void end() {
list.sort(comparator);
downstream.begin(list.size());
if (!cancellationWasRequested) {
list.forEach(downstream::accept);
}
else {
for (T t : list) {
if (downstream.cancellationRequested()) break;
downstream.accept(t);
}
}
downstream.end();
list = null;
}
@Override
public void accept(T t) {
list.add(t);
}
}
begin方法创建了ArrayList而不是数组。accept方法调用list.add添加元素。end方法调用ArrayList.sort排序。之后的处理和SizedRefSortingSink差不多。