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

10

如果我有像下面方法中所示的两个数据流:

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

我想找到所有同时存在于pendingTransactionStreamprocessedTransactionStream的对象,并根据某些标准进行分类,例如:

如果pendingTransactionStreamprocessedTransactionStream中存在具有相同transaction.getId()的事务对象,则该对象是相同的,我们可以将它们收集在一个列表中。

我尝试这样做,但出现了错误。

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

8

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

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

4
您不能多次迭代Stream。因此,您当前的代码无法工作(会出现异常,例如IllegalStateException:Stream already closed)。根据Java文档

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

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

实际上,如果您不需要PendingTransaction做其他事情,则Set更好,例如,请参见@Eran的答案

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

然后,通过检查id是否在映射中,过滤您的processedTransactionStream

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接