我无法理解StreamJava 8中的接口,特别是它Spliterator与Collector接口有关的地方.我的问题是我根本就没有理解Spliterator和Collector接口,并因此在Stream界面依然有些模糊了我.
究竟什么是a Spliterator和a Collector,我该如何使用它们?如果我愿意自己编写Spliterator或Collector(也可能是我自己的编写Stream过程),我应该做什么而不是做什么?
我阅读了一些散布在网络上的例子,但由于这里的所有内容都是新的并且可能会有变化,因此示例和教程仍然非常稀少.
为了尝试深入理解java流和分裂器,我对spliterator特性有一些微妙的问题:
Q1:Stream.empty()vsStream.of()(没有args的Stream.of())
Stream.empty():SUBSIZED,SIZEDStream.of(): SUBSIZED,IMMUTABLE,SIZED,ORDERED为什么Stream.empty()没有相同的特征Stream.of()?请注意,与Stream.concat()(特别是没有ORDERED)一起使用时会产生影响.我会说不Stream.empty()应该只有IMMUTABLE和ORDERED,还有DISTINCT和NONNULL.也很有意义Stream.of()仅具有一个参数DISTICT.
Q2:LongStream.of()没有NONNULL
刚注意到NONNULL不可用LongStream.of.不是NONNULL所有LongStreams,IntStreams和DoubleStreams 的主要特征吗?
Q3:LongStream.range(,)vsLongStream.range(,).boxed()
LongRange.range(,):SUBSIZED,IMMUTABLE,NONNULL,SIZED,ORDERED,SORTED ,DISTINCTLongStream.range(,).boxed():SUBSIZED,SIZED,ORDERED为什么.boxed()失去所有这些特征?它不应该失去任何.
我明白.mapToObj()可以失去NONNULL,IMMUTABLE和DISTICT,但.boxed()......没有意义.
Q4:.peek()输掉IMMUTABLE和NONNULL
LongStream.of(1): …
在Java 8中,Stream该类没有任何方法来包装Iterable.
相反,我Spliterator从这里Iterable获得了,然后Stream从StreamSupport这样获得一个:
boolean parallel = true;
StreamSupport.stream(spliterator(), parallel)
.filter(Row::isEmpty)
.collect(Collectors.toList())
.forEach(this::deleteRow);
Run Code Online (Sandbox Code Playgroud)
是否有产生的一些其他的方式Stream上的操作Iterable,我很想念?
我希望能够处理从必须在页面中访问的源读取的Java流.作为第一种方法,我实现了一个分页迭代器,它只是在当前页面用完项目时请求页面,然后用于StreamSupport.stream(iterator, false)获取迭代器上的流句柄.
当我发现我的页面获取非常昂贵时,我想通过并行流访问页面.在这一点上,我发现由于java直接从迭代器提供的spliterator实现,我的天真方法提供的并行性是不存在的.因为我实际上对我想要遍历的元素了解了很多(我知道在请求第一页后总结果数,并且源支持偏移和限制)我认为应该可以实现我自己的分裂器实现真正的并发(在页面元素和查询页面上完成的工作).
我已经能够很容易地实现"在元素上完成的工作"并发性,但在我最初的实现中,页面的查询只能由最顶层的分裂器完成,因此不会从分工中受益由fork-join实现提供.
如何编写实现这两个目标的分裂器?
作为参考,我将提供我到目前为止所做的事情(我知道它没有适当地划分查询).
public final class PagingSourceSpliterator<T> implements Spliterator<T> {
public static final long DEFAULT_PAGE_SIZE = 100;
private Page<T> result;
private Iterator<T> results;
private boolean needsReset = false;
private final PageProducer<T> generator;
private long offset = 0L;
private long limit = DEFAULT_PAGE_SIZE;
public PagingSourceSpliterator(PageProducer<T> generator) {
this.generator = generator;
}
public PagingSourceSpliterator(long pageSize, PageProducer<T> generator) {
this.generator = generator;
this.limit = pageSize;
}
@Override
public boolean tryAdvance(Consumer<? super T> action) {
if (hasAnotherElement()) {
if …Run Code Online (Sandbox Code Playgroud) SpliteratorJava 8中的类有什么好的用例场景?
在Java 8中,提供了各种方便的实用程序来从阵列构建高效的Spliterator.但是,没有提供工厂方法来构建带有比较器的Spliterator.显然,Spliterators可以附加比较器; 他们有getComparator()方法和SORTED财产.
图书馆作者如何构建SORTEDSpliterator?
是否stream.spliterator()隐式关闭stream,或者之后是否需要明确关闭它?
Stream<String> stream = Stream.of("a", "b", "c");
Spliterator<T> spliterator = stream.spliterator();
// Some low lever operation with the spliterator
stream.close(); // do we need to close?
Run Code Online (Sandbox Code Playgroud)
乍一看,似乎该.spliterator()方法关闭了stream,但没有调用stream.close().至少如果我在.spliterator()调用方法后立即将其关闭,似乎不会影响分裂器操作.
Stream<String> stream = Stream.of("a", "b", "c").limit(2);
Spliterator<T> spliterator = stream.spliterator();
stream.close();
// Some low lever operation with the spliterator
Run Code Online (Sandbox Code Playgroud)
这个问题可以扩展到其他stream方法,例如,.findAny().
stream.findAny() // Can I assume that I don't need to close the stream?
stream.onClose(() -> System.out.println("hi!")).findAny()`
// …Run Code Online (Sandbox Code Playgroud) 在Java 1.8.0_25发布之后,有一个有趣的情况...我认为我的问题的根源主要与Interfaces中"默认"实现的新(到1.8)功能有关.
我正在开发的应用程序目前的目标是1.7,到目前为止一直运行良好.直到用户开始更新到1.8.现在我们的用户已经开始更新到1.8,我们的手被迫转向1.8支持.
我们已经修复了大部分问题(主要与1.7和1.8之间的JavaFX包的更改有关),但还有一个棘手的问题.
在我的智慧或缺乏中,我不久前决定创建一个从AbstractList <T>扩展的SortedList <T>.到目前为止,这个类运行良好,但是当在1.8运行时运行时,我得到:
Duplicate methods named spliterator with the parameters () and () are inherited
from the types Collection<T> and Iterable<T>
Run Code Online (Sandbox Code Playgroud)
对我来说,这似乎是由AbstractList <T>实现的一些接口中的"默认"实现引起的(我的SortedList <T>类没有实现除Serializable之外的任何其他接口).实现Serializable是我们的另一个问题,因为我们需要支持SortedList <T>对象的反序列化,没有办法解决这个问题!).
我可以通过在SortedList <T>类中提供spliterator()的覆盖实现来消除错误.但是,如果构建它,它将不再在Java 1.7环境中运行.如果我尝试使用1.7运行时的SortedList <T>,我得到:
Problem:
Error: Unresolved compilation problems:
The import java.util.Spliterator cannot be resolved
Spliterator cannot be resolved to a type
com.xxxx.xxxx.util.SortedList.<init>(SortedList.java:13)
Run Code Online (Sandbox Code Playgroud)
这个错误非常明显,因为我们现在已经覆盖了SortedList <T>中的spliterator()方法,它需要包含java.util.Spliterator,但1.7中不存在.
理想情况下,如果他们不愿意,我们不希望我们的客户更新到Java 1.8.
我们的手被逼到了吗?我们是否需要强制用户更新到1.8,并为自己更新为1.8的用户推出新版本?
有没有人知道解决这个问题的方法?
在一个更哲学的说明中,为什么接口已被实现损坏:-(.可能是一个漂亮的新功能,但它们确实应该避免做任何会导致对现有代码进行重大更改的事情,特别是在列表如此基本的事情上/收藏等
任何有关这种困境的帮助或建议将不胜感激.
干杯,
标记
我在学习的过程中认识到这Parallelism是一个主要优势Spliterator.
这可能是一个基本的问题,但任何人都可以解释我的主要差异Iterator,并Spliterator和举一些例子?
我知道设置并行处理会有开销,Stream如果项目很少或者每个项目的处理速度很快,单个线程中的处理速度会更快.
但是,是否存在类似的阈值trySplit(),将问题分解为较小的块会产生相反的效果?我在想类似于合并排序切换到最小块的插入排序.
如果是这样,阈值是否取决于过程中物品的相对成本trySplit()和消耗tryAdvance()?例如,考虑一个分裂操作,它比推进数组索引要复杂得多 - 分割一个词法排序的多集排列.是否存在允许客户在创建并行流时指定拆分下限的约定,具体取决于其使用者的复杂程度?启发式Spliterator可以用来估计下限本身吗?
或者,或者,让a的下限为Spliterator1 是否总是安全的,让工作窃取算法负责选择是否继续拆分?
spliterator ×10
java-8 ×9
java ×8
java-stream ×4
iterator ×2
concurrency ×1
fork-join ×1
interface ×1
iterable ×1
lambda ×1