[英]Intersection of two collections of different objects types java 8
I have two lists of objects: 我有两个对象列表:
List<SampleClassOne> listOne;
List<SampleClassTwo> listTwo;
SampleClassOne: SampleClassOne:
public class SampleClassOne{
private String myFirstProperty;
//ommiting getters-setters
}
SampleClassTwo: SampleClassTwo:
public class SampleClassTwo{
private String myOtherProperty;
//ommiting getters-setters
}
RootSampleClass: RootSampleClass:
public class RootSampleClass{
private SampleClassOne classOne;
private SampleClassTwo classTwo;
//ommiting getters-setters
}
Now I would like to merge two lists into new list of type RootSampleClass based on condition: 现在我想根据条件将两个列表合并到RootSampleClass类型的新列表中:
if(classOneObject.getMyFirstProperty().equals(classTwoObject.getMyOtherProperty()){
//create new RootSampleClass based on classOneObject and classTwoObject and add it to another collection
}
Pseudo code: 伪代码:
foreach(one: collectionOne){
foreach(two: collectionTwo){
if(one.getMyFirstProperty().equals(two.getMyOtherProperty()){
collectionThree.add(new RootSampleClass(one, two));
}
}
}
I am interested in java 8. I would like to have the best performance here that's why I am asking for existing solution without writing custom foreach. 我对java 8感兴趣。我想在这里有最好的表现,这就是为什么我要求现有的解决方案而不编写自定义foreach。
A direct equivalent to the nested loops is 直接等效于嵌套循环
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());
with an emphasis on direct equivalent , which includes the bad performance of doing n×m operations. 重点是直接等效 ,其中包括做n×m操作的不良表现。
A better solution is to convert one of the lists into a data structure supporting an efficient lookup, eg a hash map. 更好的解决方案是将其中一个列表转换为支持有效查找的数据结构,例如哈希映射。 This consideration is independent of the question which API you use.
此考虑因素与您使用的API的问题无关。 Since you asked for the Stream API, you can do it like this:
既然您要求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());
Note that both solutions will create all possible pairings in case, a property value occurs multiple times within either or both lists. 请注意,两种解决方案都会创建所有可能的配对,以便在一个或两个列表中多次出现属性值。 If the property values are unique within each list, like IDs, you can use the following solution:
如果属性值在每个列表中都是唯一的,例如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());
If you don't mind potentially performing double lookups, you could replace the last solution with the following more readable code: 如果您不介意可能执行双重查找,则可以使用以下更易读的代码替换最后一个解决方案:
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.