[英]Using Java 8 Streams to accomplish removing loops
I have a list of documents objects that need to be mapped based on certain criteria.我有一个需要根据某些标准进行映射的文档对象列表。 There is a utility function that takes any 2 document types and determines if they match on a number of criteria, like genre of document, whether they share any authors etc. The code works but I';d like to use Java Streams to solve it if possible.有一个实用程序函数可以接受任何 2 种文档类型,并确定它们是否符合许多标准,例如文档类型、它们是否共享任何作者等。代码有效,但我想使用 Java Streams 来解决它如果可能的话。
I currently solve this by using the following code:我目前使用以下代码解决了这个问题:
class Document{
private String genre;
private List<Author> authors;
private String isbn;
private boolean paperBack;
...
}
I also use a library utility that has a function that returns true given a series of matching criteria and a pair of documents.我还使用了一个库实用程序,该实用程序具有在给定一系列匹配条件和一对文档的情况下返回 true 的函数。 It simply returns a boolean.它只是返回一个布尔值。
boolean matchesOnCriteria(Document doc1, Document doc2, Criteria criteria){
...
}
Here is the matching code for finding the books that match on the provided criteria这是查找符合提供条件的书籍的匹配代码
DocumentUtils utils = DocumentUitls.instance();
Criteria userCriteria = ...
List<Pair> matches = new ArrayList<>();
List<Document> documents = entityManager.findBy(.....);
for(Document doc1 : documents){
for(Documents doc2 : documents){
if(!doc1.equals(doc2){
if (utils.matchesOnCriteria(doc1,doc2, userCriteria)) {
Pair<Document> p = new Pair(doc1,doc2);
if(!matches.contains(p)){
matches.add(p);
}
}
}
}
}
}
How can I do this using Streams?如何使用 Streams 执行此操作?
The idea of the following solution using Steam::reduce
is simple:以下使用Steam::reduce
解决方案的想法很简单:
Group the qualified pairs of documents to Map<Document, List<Document>>
having all possible acceptable combinations.将合格的文档对分组为具有所有可能的可接受组合的Map<Document, List<Document>>
。 Let's say odd and even documents are in pairs:假设奇数和偶数文档是成对的:
D1=[D3, D5], D2=[D4], D3=[D1, D5], D4=[D2], D5[D1, D3] // dont mind the duplicates
Using Stream::reduce
you can achieve the following steps:使用Stream::reduce
可以实现以下步骤:
Transform entries to Pair<>
,将条目转换为Pair<>
,
D1-D3, D1-D5, D2-D4, D3-D1, D1-D5, D4-D2, D5-D1, D5-D3
Save these items to Set
guaranteeing the equal pairs occur once ( D1-D3
= D3-D1
).将这些项目保存到Set
保证相等对出现一次( D1-D3
= D3-D1
)。 The condition the Pair
must override both Object::equals
and Object:hashCode
and implements equality based on the both documents present. Pair
必须覆盖Object::equals
和Object:hashCode
并根据存在的两个文档实现相等。
D1-D3, D1-D5, D3-D5, D2-D4
Reducing (merging) the particular sets into a single collection Set<Pair<Document>>
.将特定集合减少(合并)为单个集合Set<Pair<Document>>
。
Map<Document, List<Document>> map = documents.stream()
.collect(Collectors.toMap( // Collected to Map<Document, List<Document>>
Function.identity(), // Document is the key
d1 -> documents.stream() // Value are the qualified documents
.filter(d2 -> !d1.equals(d2) &&
utils.matchesOnCriteria(d1,d2, userCriteria)
.collect(Collectors.toList()))); // ... as List<Document>
Set<Pair<Document>> matches = map.entrySet().stream().reduce( // Reduce the Entry<Dokument, List<Document>>
new HashSet<>(), // ... to Set<Pair<>>
(set, e) -> {
set.addAll(e.getValue().stream() // ... where is
.map(v -> new Pair<Document>(e.getKey(), v)) // ... the Pair of qualified documents
.collect(Collectors.toSet()));
return set;
},
(left, right) -> { left.addAll(right); return left; }); // Merge operation
The condition !matches.contains(p)
is redundant, there are better ways to assure distinct values.条件!matches.contains(p)
是多余的,有更好的方法来确保不同的值。 Either use Stream::distinct
or collect the stream to Set
which is an unordered distinct collection.使用Stream::distinct
或将流收集到Set
,这是一个无序的不同集合。
Read more at Baeldung's: remove all duplicates .在Baeldung 上阅读更多信息:删除所有重复项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.