Search code examples
javalistsetjava-stream

How do I make an advanced stream that both matches and compares where no match at the same time?


I have two lists (List1 and List2) of Person objects:

public class Person {

  ObjectId id;
  private List<String> names;
  private Integer age;

}

I want to compare the Lists, and wherever there is a match on id, I want to check if the age matches. If age does match, then I don't want to do anything but if there is a mismatch in age then I want to return the names.

So I should end up with one Set (no duplicates) that contains names from all the objects that has ids in both lists but a mismatch in age.


Solution

  • You could filter both lists, concatnate them and flatmap to the names. Something like:

    import java.util.List;
    import java.util.Objects;
    import java.util.Set;
    import java.util.function.BiPredicate;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    ....
    
    
    List<Person> list1 = //your first list
    List<Person> list2 = //your second list
    
    BiPredicate<Person,Person> sameIdDiffAge = (p1,p2) -> Objects.equals(p1.getId(),  p2.getId()) &&
                                                         !Objects.equals(p1.getAge(), p2.getAge());
    Set<String> result =
            Stream.concat(list1.stream().filter(p1 -> list2.stream().anyMatch(p2 -> sameIdDiffAge.test(p1,p2))),
                          list2.stream().filter(p1 -> list1.stream().anyMatch(p2 -> sameIdDiffAge.test(p1,p2))))
            .flatMap(p -> p.getNames().stream())
            .collect(Collectors.toSet());