总之,以下代码用于过滤第二个参数中实体的第一个参数。如果一个'改变''在第二个参数中指定,它应该过滤较窄的结果。
当我运行这个时,我得到一个错误:#IllegalStateException:stream已经被操作或关闭。'
有没有办法可以重复使用相同的流?
我见过人们实现像Supplier>这样的东西,但我认为这不适用于这种情况。或者,我对它的理解并不熟悉,以了解如何使用供应商。
/**
* Filters through DocumentAuditEntityListing to find existence of the entities
* ActionEnum, ActionContextEnum, LevelEnum, & StatusEnum.
*
* @param audits A list of audits to search
* @param toFind The audit entities to find
* @return If entities found, return DocumentAudit, else null
*/
public DocumentAudit verifyAudit(DocumentAuditEntityListing audits, DocumentAudit toFind) {
//Filter for proper entities
Stream stream = audits.getEntities().stream().filter(doc -> (
doc.getAction().equals(toFind.getAction())) &&
doc.getActionContext().equals(toFind.getActionContext()) &&
doc.getLevel().equals(toFind.getLevel()) &&
doc.getStatus().equals(toFind.getStatus()));
//If changes were specified, filter further.
if (toFind.getChanges() != null){
stream.filter(change -> (toFind.getChanges().contains(change)));
}
return (DocumentAudit) stream.findFirst().orElse(null);
}
答案 0 :(得分:7)
您需要使用stream = stream.filter(change -> ...)
分配结果流。
还使流类型安全(即Stream<DocumentAudit>
)。自Java 5以来,泛型一直存在,所以你没有理由使用原始类型。
Stream<DocumentAudio> stream = audits.getEntities().stream()
.filter(doc ->
doc.getAction().equals(toFind.getAction())) &&
doc.getActionContext().equals(toFind.getActionContext()) &&
doc.getLevel().equals(toFind.getLevel()) &&
doc.getStatus().equals(toFind.getStatus());
if (toFind.getChanges() != null){
stream = stream.filter(change -> toFind.getChanges().contains(change));
}
return stream.findFirst().orElse(null);
答案 1 :(得分:2)
Supplier
不是技巧,而只是用于促进新流的创建。规则仍然相同 - 在任何情况下都不能重用流。使用Supplier
的一般方法是这样的:
Supplier<Stream<Something>> sup = () -> yourList.stream();
因此,每次拨打sup.get()
时,您都会收到新的Stream
。这没什么好看的,只是风格问题。
实际上你的问题与我已经看过的问题有点不同。基本上你在做:
Stream<Some> s = ...
s.filter
s.filter
s.forEach
我发现错误消息在这里有点误导,stream has already been operated upon or closed
实际上意味着单终端或中间操作只能应用一次一个Stream
。如果在错误消息中更清楚,那就更有意义了。
答案 2 :(得分:1)
错误消息令人困惑,因为没有重用流(只调用了一个终端操作,即findFirst()
)。
但是,正如其他人所指出的,stream.filter(...)
块中if
的应用程序正在丢失,因为filter
操作返回的流永远不会被赋予变量。这是造成这种混淆错误的原因。
尽管如此,我还想向您展示另一种处理此要求的方法。您可以先处理谓词,然后在准备好之后将其传递给stream.filter(...)
操作,而不是有条件地应用额外的过滤器:
Predicate<DocumentAudit> pred = doc ->
doc.getAction().equals(toFind.getAction()) &&
doc.getActionContext().equals(toFind.getActionContext()) &&
doc.getLevel().equals(toFind.getLevel()) &&
doc.getStatus().equals(toFind.getStatus());
// If changes were specified, filter further.
if (toFind.getChanges() != null) {
pred = pred.and(change -> toFind.getChanges().contains(change));
}
return audits.getEntities().stream()
.filter(pred)
.findFirst()
.orElse(null);
一些评论......
我用Predicate.and
来组成条件。
你在最后一行使用原始流和强制转换。请不要再这样做了。我们在2017年......
理想情况下,您应该使用Optional
作为方法的返回值(而不是返回找到的对象或null
)。这样,您的方法的用户可以提前知道可能已找到该对象。他们甚至可以使用Optional
方便的操作来有条件地对对象执行操作,或有条件地将其映射到其某些属性等。