[英]Intersection of two collections of different objects types java 8
我有兩個對象列表:
List<SampleClassOne> listOne;
List<SampleClassTwo> listTwo;
SampleClassOne:
public class SampleClassOne{
private String myFirstProperty;
//ommiting getters-setters
}
SampleClassTwo:
public class SampleClassTwo{
private String myOtherProperty;
//ommiting getters-setters
}
RootSampleClass:
public class RootSampleClass{
private SampleClassOne classOne;
private SampleClassTwo classTwo;
//ommiting getters-setters
}
現在我想根據條件將兩個列表合並到RootSampleClass類型的新列表中:
if(classOneObject.getMyFirstProperty().equals(classTwoObject.getMyOtherProperty()){
//create new RootSampleClass based on classOneObject and classTwoObject and add it to another collection
}
偽代碼:
foreach(one: collectionOne){
foreach(two: collectionTwo){
if(one.getMyFirstProperty().equals(two.getMyOtherProperty()){
collectionThree.add(new RootSampleClass(one, two));
}
}
}
我對java 8感興趣。我想在這里有最好的表現,這就是為什么我要求現有的解決方案而不編寫自定義foreach。
直接等效於嵌套循環
List<RootSampleClass> result = listOne.stream()
.flatMap(one -> listTwo.stream()
.filter(two -> one.getMyFirstProperty().equals(two.getMyOtherProperty()))
.map(two -> new RootSampleClass(one, two)))
.collect(Collectors.toList());
重點是直接等效 ,其中包括做n×m操作的不良表現。
更好的解決方案是將其中一個列表轉換為支持有效查找的數據結構,例如哈希映射。 此考慮因素與您使用的API的問題無關。 既然您要求Stream API,您可以這樣做:
Map<String,List<SampleClassOne>> tmp=listOne.stream()
.collect(Collectors.groupingBy(SampleClassOne::getMyFirstProperty));
List<RootSampleClass> result = listTwo.stream()
.flatMap(two -> tmp.getOrDefault(two.getMyOtherProperty(), Collections.emptyList())
.stream().map(one -> new RootSampleClass(one, two)))
.collect(Collectors.toList());
請注意,兩種解決方案都會創建所有可能的配對,以便在一個或兩個列表中多次出現屬性值。 如果屬性值在每個列表中都是唯一的,例如ID,則可以使用以下解決方案:
Map<String, SampleClassOne> tmp=listOne.stream()
.collect(Collectors.toMap(SampleClassOne::getMyFirstProperty, Function.identity()));
List<RootSampleClass> result = listTwo.stream()
.flatMap(two -> Optional.ofNullable(tmp.get(two.getMyOtherProperty()))
.map(one -> Stream.of(new RootSampleClass(one, two))).orElse(null))
.collect(Collectors.toList());
如果您不介意可能執行雙重查找,則可以使用以下更易讀的代碼替換最后一個解決方案:
Map<String, SampleClassOne> tmp=listOne.stream()
.collect(Collectors.toMap(SampleClassOne::getMyFirstProperty, Function.identity()));
List<RootSampleClass> result = listTwo.stream()
.filter(two -> tmp.containsKey(two.getMyOtherProperty()))
.map(two -> new RootSampleClass(tmp.get(two.getMyOtherProperty()), two))
.collect(Collectors.toList());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.