Java 处理两个没有(不必要的)嵌套循环的相关列表

Java 处理两个没有(不必要的)嵌套循环的相关列表,java,java-stream,Java,Java Stream,我有一份书单和一份作者名单。书籍只有authorId(不是整个对象)。我需要多次处理书籍列表(几个不同的需求)。有些需求也需要作者提供的数据 因此,很明显,对于每本书,都必须通过authorId搜索作者。但如何以最佳方式(仅一次)做到这一点 Book=。。。 可选authorO=authors.stream .filter(author->author.getId().equals(book.getAuthorId())) .findFirst(); 我不知何故猜测,在收集流中应该有一个语法来

我有一份书单和一份作者名单。书籍只有
authorId
(不是整个对象)。我需要多次处理书籍列表(几个不同的需求)。有些需求也需要作者提供的数据

因此,很明显,对于每本书,都必须通过
authorId
搜索
作者。但如何以最佳方式(仅一次)做到这一点

Book=。。。
可选authorO=authors.stream
.filter(author->author.getId().equals(book.getAuthorId()))
.findFirst();
我不知何故猜测,在收集流中应该有一个语法来“合并”两个列表,然后(收集?)多次处理结果

所以我想要这样的东西。你能告诉我怎么做吗?多谢各位

List<Book> books = ...
List<Author> authors = ...

books.stream()
     .??? // stream of pairs? 
     .forEach((book, author) -> {
         processingOne(book, author);

         if (featureFlag2) {
             processingTwo(book, author);
         }

         // ...
    });
列出书籍=。。。
列出作者=。。。
books.stream()
.??? // 成双成对?
.forEach((书、作者)->{
加工单(书、作者);
如果(功能标志2){
处理2(书、作者);
}
// ...
});

我建议您在开始处理图书列表之前,先创建一个地图,以
authorId
为键,以
Author
为值:

Map authorMap=authors.stream()
.collect(Collectors.toMap)(作者::getAuthorId,
Function.identity());
然后对图书列表进行流式处理,如下所示:

books.stream()
.forEach(书->{
Author=authorMap.get(book.getAuthorId());
加工单(书、作者);
如果(功能标志2){
处理2(书、作者);
}
//...
});
编辑:以不同的方式完成相同的操作。这种方法利用了有状态的lambda

public Consumer processor(列出作者,boolean featureFlag2){
//如果使用parallelStream,请使用并发映射
//authorMap是状态。仅为流创建一次。
地图作者地图
=authors.stream()
.collect(Collectors.toMap)(作者::getAuthorId,
Function.identity());
还书->{
Author=authorMap.get(book.getAuthorId());
加工单(书、作者);
如果(功能标志2){
处理2(书、作者);
}
};
}
现在在您的流中使用此
消费者

books.forEach(处理器(作者、功能标志2));

我建议您在开始处理图书列表之前,先创建一个地图,以
authorId
为键,以
Author
为值:

Map authorMap=authors.stream()
.collect(Collectors.toMap)(作者::getAuthorId,
Function.identity());
然后对图书列表进行流式处理,如下所示:

books.stream()
.forEach(书->{
Author=authorMap.get(book.getAuthorId());
加工单(书、作者);
如果(功能标志2){
处理2(书、作者);
}
//...
});
编辑:以不同的方式完成相同的操作。这种方法利用了有状态的lambda

public Consumer processor(列出作者,boolean featureFlag2){
//如果使用parallelStream,请使用并发映射
//authorMap是状态。仅为流创建一次。
地图作者地图
=authors.stream()
.collect(Collectors.toMap)(作者::getAuthorId,
Function.identity());
还书->{
Author=authorMap.get(book.getAuthorId());
加工单(书、作者);
如果(功能标志2){
处理2(书、作者);
}
};
}
现在在您的流中使用此
消费者

books.forEach(处理器(作者、功能标志2));

并非所有收集处理都必须通过流API完成。您是否坚持使用流API来执行您所需的处理?同意,我只是看不到一个优雅的解决方案,所以我问。如果你有任何类型/方式的好/优雅的解决方案,只需将其作为答案发布即可。假设它可以是反应性的,使用通量处理。。。但主要的问题是最小化m*n的计算难度。。。具有尽可能多的可读性。并非所有的集合处理都必须通过流API完成。您是否坚持使用流API来执行您所需的处理?同意,我只是看不到一个优雅的解决方案,所以我问。如果你有任何类型/方式的好/优雅的解决方案,只需将其作为答案发布即可。假设它可以是反应性的,使用通量处理。。。但主要的问题是最小化m*n的计算难度。。。具有尽可能多的可读性。这些方法是相同的。在第二种方法中,您只是将第一种方法的一部分代码封装到一个方法中。顺便说一句,除了
books.stream().forEach(…)
之外,你还可以编写
books.forEach(…)
@Holger,这就是为什么我提到了“做同样事情的另一种方法”:-:-:-)看起来,当需要进行多次处理时,它会遍历列表数次…@Wooff不,两个列表只遍历一次。作者列表遍历一次以创建地图,书籍列表遍历一次以进行处理这些方法是相同的。在第二种方法中,您只是将第一种方法的一部分代码封装到一个方法中。顺便说一下,除了
books.stream().forEach(…)
之外,您还可以编写
books.forEach(…)List<Book> books = ...
List<Author> authors = ...

books.stream()
     .??? // stream of pairs? 
     .forEach((book, author) -> {
         processingOne(book, author);

         if (featureFlag2) {
             processingTwo(book, author);
         }

         // ...
    });