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

时间:2019-01-15 07:09:25

标签: java java-8 java-stream

如果我有2条流,例如采用如下所示的方法

public Stream<Transaction> getPendingTransaction(Stream<PendingTransaction> pendingTransactionStream,Stream<ProcessedTransaction> processedTransactionStream){ }

,我想根据

这样的条件,找到pendingTransactionStream中存在的所有对象,而processedTransactionStream中也存在所有对象
  

如果transaction.getId()与存在于   pendingTransactionStreamprocessedTransactionStreamthen   对象是相同的,我们可以将它们收集在列表中。

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

processedTransactionStream
        .filter( (processedTransaction)->
        {
            pendingTransactionStream.anyMatch(s->s.getTransactionId().equals(processedTransaction.getTransactionId()) );
        } 
        ).collect(Collectors.toList());

2 个答案:

答案 0 :(得分:7)

好吧,您不能多次消费pendingTransactionStream Stream。您可以将其转换为List方法中使用的Set(甚至更好的是filter)交易ID。

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

答案 1 :(得分:4)

您不能多次重复Stream。因此,您当前的代码无效(您会收到IllegalStateException: Stream already closed之类的异常。来自java doc

  

流应操作(调用中间流或终端流操作)仅一次

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

  

实际上,Set会更好,因为您不需要PendingTransaction来做其他任何事情,例如看一下@Eran's answer

Map<String, PendingTransaction> pendingTransactionMap = pendingTransactionStream
    .collect(PendingTransaction::getId, Function.identity());

然后通过检查ID是否在地图上来filter您的processedTransactionStream

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