存在一个关于java方法是否应该返回Collections or Streams的问题,在该问题中Brian Goetz回答说,即使对于有限序列,通常也应该首选Streams。
但是在我看来,目前无法安全地执行来自其他地方的Streams上的许多操作,并且防御性的代码保护措施是不可能的,因为Streams不会显示它们是无限的还是无序的。
如果要在Stream()上执行的操作遇到并行问题,我可以调用isParallel()进行检查或顺序执行,以确保计算是并行的(如果我记得的话)。
但是,如果有序性或无穷大(大小)与我的程序的安全性有关,则我无法编写保护措施。
假设我使用了一个实现此虚拟接口的库:
public interface CoordinateServer {
public Stream<Integer> coordinates();
// example implementations:
// IntStream.range(0, 100).boxed() // finite, ordered, sequential
// final AtomicInteger atomic = new AtomicInteger();
// Stream.generate(() -> atomic2.incrementAndGet()) // infinite, unordered, sequential
// Stream.generate(() -> atomic2.incrementAndGet()).parallel() // infinite, unordered, parallel
}
那我可以安全地对此流调用哪些操作以编写正确的算法?
看来,如果我想将元素写入文件是一种副作用,我需要担心流是并行的:
// if stream is parallel, which order will be written to file?
coordinates().peek(i -> {writeToFile(i)}).count();
// how should I remember to always add sequential() in such cases?
并且如果是并行的,则基于并行的Threadpool?
如果我想对流进行排序(或其他非短路操作),则在某种程度上需要谨慎对待它的无限性:
coordinates().sorted().limit(1000).collect(toList()); // will this terminate?
coordinates().allMatch(x -> x > 0); // will this terminate?
我可以在排序之前强加一个限制,但是如果我希望有一个未知大小的有限流,那应该是哪个幻数呢?
最后,也许我想并行计算以节省时间,然后收集结果:
// will result list maintain the same order as sequential?
coordinates().map(i -> complexLookup(i)).parallel().collect(toList());
但是,如果不对流进行排序(在该库的该版本中),则由于并行处理,结果可能会混乱。但是除了不使用并行(这违反了性能目的)之外,我该如何防范呢?
集合是明确的关于是有限的还是无限的,关于是否有序,并且它们不带有处理模式或线程池。这些似乎是API的宝贵属性。
此外,Streams may sometimes need to be closed,但最常见的不是。如果我使用某个方法的流(来自某个方法参数的),通常应该调用close吗?
另外,流可能已经被消耗掉了,能够优雅地处理这种情况将是一件好事,因此check if the stream has already been consumed;
我希望有一些代码片段,可用于在处理之前验证有关流的假设,例如>
Stream<X> stream = fooLibrary.getStream();
Stream<X> safeStream = StreamPreconditions(
stream,
/*maxThreshold or elements before IllegalArgumentException*/
10_000,
/* fail with IllegalArgumentException if not ordered */
true
)
答案 0 :(得分:2)
据我所知(经过一些实验和here)后,还无法确定流是否是有限的。
除此之外,有时甚至在运行时也无法确定(例如在Java 11-chainID
中)。
您可以做的是:
您可以通过几种方式确定它是否是有限的(请注意,在这些方法上接收到false并不意味着它是无限的,只是可能是无限的):
chainID teamID statID startType endType
2 Team B Entry TO SH
2 Team B Shot TO SH
3 Team A Entry ST TO
3 Team A Ineffective Pass ST TO
4 Team B Effective Pass TO ST
4 Team B Effective Pass TO ST
4 Team B Ineffective Pass TO ST
5 Team A Entry TO SH
5 Team A Goal TO SH
-如果已知的确切大小是有限的,否则它将返回-1。
IntStream.generate(() -> 1).takeWhile(x -> externalCondition(x))
-如果为stream.spliterator().getExactSizeIfKnown()
,则返回true。
您可以假设最坏的情况(取决于您的情况)来保护自己。
stream.spliterator().hasCharacteristics(Spliterator.SIZED)
-明确设置您的首选消费类型。对于潜在的无限流,假设每种情况下的最坏情况。
SIZED
-它会反复进行,直到出现此类推文为止(或永远如此)。stream.sequential()/stream.parallel()
或stream.filter(tweet -> isByVenkat(tweet)).findAny()
或类似操作)之前先调用stream.limit(x)
,其中collect
是您愿意接受的尝试次数。毕竟,我只想提一下,我认为返回流通常不是一个好主意,除非有很大的好处,否则我会尽量避免使用它。