假设我有一个方法将只读视图返回到成员列表:
class Team {
private List < Player > players = new ArrayList < > ();
// ...
public List < Player > getPlayers() {
return Collections.unmodifiableList(players);
}
}
Run Code Online (Sandbox Code Playgroud)
进一步假设所有客户端都立即迭代一次列表.也许将玩家放入JList或其他东西.客户端就不能存储到列表的引用以便稍后进行检查!
鉴于这种常见情况,我应该返回一个流吗?
public Stream < Player > getPlayers() {
return players.stream();
}
Run Code Online (Sandbox Code Playgroud)
或者在Java中返回非惯用的流?设计的流是否始终在它们创建的同一表达式中"终止"?
如果我们使用Java 8 Stream就像list.stream().filter(....).collect(..).....它什么时候关闭这个流?
作为下一个例子,我们关闭流我们是好的做法吗?
Stream<String> stream = list.stream();
String result = stream.limit(10).collect(Collectors.joining(""));
stream.close();
Run Code Online (Sandbox Code Playgroud) 在进行流操作时,在中间/ pleleline操作期间,将创建具有不同特征的流(例如,SORTED/SIZED/DISTINCT/ORDERED) - 掌握Lambdas(第6章)
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
Run Code Online (Sandbox Code Playgroud)
我们如何找出上面代码段中提到的流的不同特征?
我有一种情况,我正在读取数据库并返回a List<String>,其中每个字符串被选中并根据某些条件添加到列表中.方法签名是:
public List<String> myMethod(String query, int limit)
Run Code Online (Sandbox Code Playgroud)
第二个参数提供返回列表大小的上限(设置limit=-1将删除任何大小限制).为了避免使这个方法占用大量内存,我编写了一个返回Stream<String>而不是列表的等效方法.(注意:我不需要随机访问返回的元素或任何其他特定于列表的功能.)
但是,我对返回a有点怀疑Stream<>,特别是因为该方法是公开的.使用Stream<>Java 返回公共方法是否安全?
我如何检查流实例是否已被使用(意味着已经调用了终端操作,使得对终端操作的任何进一步调用都可能失败IllegalStateException: stream has already been operated upon or closed.?
理想情况下,我想要一个不消耗流的方法,如果该流尚未被消耗,则返回一个布尔值false(如果流被消耗而没有IllegalStateException从流方法中捕获)(因为对控制流使用Exception代价很高并且容易出错) ,尤其是在使用标准例外时)。
与hasNext()Iterator中类似的方法,它具有异常抛出和布尔返回行为(尽管没有约定to next())。
例:
public void consume(java.util.function.Consumer<Stream<?>> consumer, Stream<?> stream) {
consumer.accept(stream);
// defensive programming, check state
if (...) {
throw new IllegalStateException("consumer must call terminal operation on stream");
}
}
Run Code Online (Sandbox Code Playgroud)
目标是如果客户端代码在不消耗流的情况下调用此方法,则会尽早失败。
似乎没有办法做到这一点,我必须添加一个try-catch块来调用任何终端操作,例如iterator(),捕获异常并抛出一个新异常。
可以接受的答案也可以是“不存在解决方案”,其中有充分的理由说明为什么规范无法添加这种方法(如果存在良好的理由)。似乎JDK流通常在其终端方法的开头具有以下代码片段:
// in AbstractPipeline.java
if (linkedOrConsumed)
throw new IllegalStateException(MSG_STREAM_LINKED);
Run Code Online (Sandbox Code Playgroud)
因此,对于那些流,实现这种方法似乎并不那么困难。
我知道Java中有无限的流.
有没有办法检查流是否有限?
像这种方法的东西isStreamFinite(Stream<T> stream)?
@Test
public void testStreamFinity() {
assertFalse(isStreamFinite(generateLong()));
}
private <T> boolean isStreamFinite(Stream<T> stream) {
if (stream.count() < Long.MAX_VALUE) {
return true;
}
return false;
}
private Stream<Long> generateLong() {
return LongStream.generate(() -> new Random().nextLong()).boxed();
}
Run Code Online (Sandbox Code Playgroud)
Stream的构造会留下一些标记/轨迹,我们可以用它来追溯检查它吗?
该检查方法是可靠的预期总是能工作吗?
在尝试通过检测isFinite流来解决问题时,我错了.如上所述,答案似乎不稳定/可靠.我会在另一个地方重构我的解决方案.谢谢你的帮助〜