[英]Using Java 8 Streams to accomplish removing loops
我有一個需要根據某些標准進行映射的文檔對象列表。 有一個實用程序函數可以接受任何 2 種文檔類型,並確定它們是否符合許多標准,例如文檔類型、它們是否共享任何作者等。代碼有效,但我想使用 Java Streams 來解決它如果可能的話。
我目前使用以下代碼解決了這個問題:
class Document{
private String genre;
private List<Author> authors;
private String isbn;
private boolean paperBack;
...
}
我還使用了一個庫實用程序,該實用程序具有在給定一系列匹配條件和一對文檔的情況下返回 true 的函數。 它只是返回一個布爾值。
boolean matchesOnCriteria(Document doc1, Document doc2, Criteria 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);
}
}
}
}
}
}
如何使用 Streams 執行此操作?
以下使用Steam::reduce
解決方案的想法很簡單:
將合格的文檔對分組為具有所有可能的可接受組合的Map<Document, List<Document>>
。 假設奇數和偶數文檔是成對的:
D1=[D3, D5], D2=[D4], D3=[D1, D5], D4=[D2], D5[D1, D3] // dont mind the duplicates
使用Stream::reduce
可以實現以下步驟:
將條目轉換為Pair<>
,
D1-D3, D1-D5, D2-D4, D3-D1, D1-D5, D4-D2, D5-D1, D5-D3
將這些項目保存到Set
保證相等對出現一次( D1-D3
= D3-D1
)。 Pair
必須覆蓋Object::equals
和Object:hashCode
並根據存在的兩個文檔實現相等。
D1-D3, D1-D5, D3-D5, D2-D4
將特定集合減少(合並)為單個集合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
條件!matches.contains(p)
是多余的,有更好的方法來確保不同的值。 使用Stream::distinct
或將流收集到Set
,這是一個無序的不同集合。
在Baeldung 上閱讀更多信息:刪除所有重復項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.