Intersection of two sets of different types of java 8 objects

I have two lists of objects:

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
}

Now I would like to merge the two lists into a new list of type RootSampleClass based on the condition:

if(classOneObject.getMyFirstProperty().equals(classTwoObject.getMyOtherProperty()){
 //create new RootSampleClass based on classOneObject and classTwoObject and add it to another collection
}

Pseudocode:

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 for me to have better performance, so I ask for the existence of a solution without writing a custom foreach.

+4
source share
1 answer

The direct equivalent of 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 a focus on the direct equivalent, which includes poor n × m performance.

, , . -. , 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());

, , . , , :

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());
+7

All Articles