如何在Java 8中的两个Streams之间进行搜索

sau*_*m22 10 java java-8 java-stream

如果我有2个Streams,如下面所示的方法

public Stream<Transaction> getPendingTransaction(Stream<PendingTransaction> pendingTransactionStream,Stream<ProcessedTransaction> processedTransactionStream){ }
Run Code Online (Sandbox Code Playgroud)

我想找到其中存在的所有对象中pendingTransactionStream同样存在于processedTransactionStream基于像一些标准

if transaction.getId()对于存在的Transaction对象是相同的, pendingTransactionStream并且processedTransactionStreamthen该对象是相同的,我们可以在列表中收集它们.

我尝试这样做,但它给出了错误

processedTransactionStream
        .filter( (processedTransaction)->
        {
            pendingTransactionStream.anyMatch(s->s.getTransactionId().equals(processedTransaction.getTransactionId()) );
        } 
        ).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

Era*_*ran 7

好吧,你不能pendingTransactionStream Stream多次消费.您可以将其转换为要在方法中使用的List(或甚至更好的Set)a 事务ID filter.

Set<String> pending = pendingTransactionStream.map(PendingTransaction::getTransactionId)
                                              .collect(Collectors.toSet());
List<ProcessedTransaction> processed = 
    processedTransactionStream.filter(pt -> pending.contains(pt.getTransactionId()))
                              .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)


Lin*_*ica 4

您不能Stream多次迭代 s 。所以你当前的代码不起作用(你会得到一个异常,如IllegalStateException: Stream already closed. 来自java doc

流只能被操作(调用中间或终端流操作)一次

一个可能的解决方案是将 转换pendingTransactionStream为一个映射,其中键是 的类型id(我使用字符串,因为我不知道 keyType):

实际上 aSet会更好,因为你不需要PendingTransaction其他任何东西,例如看看@Eran的答案

Map<String, PendingTransaction> pendingTransactionMap = pendingTransactionStream
    .collect(PendingTransaction::getId, Function.identity());
Run Code Online (Sandbox Code Playgroud)

然后filter你的processedTransactionStream,通过检查 id 是否在地图中:

List<ProcessedTransaction> processedTransactionList = processedTransactionStream
    .filter(p -> pendingTransactionMap.containsKey(p.getId()))
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)