Home > Back-end >  Can I stream the difference between two lists where a field is set to something specific in Java?
Can I stream the difference between two lists where a field is set to something specific in Java?

Time:01-03

I have the following class:

public class Person {
    private String name;
    private String gender;
}

Then I have two lists of persons

List A:

index 0: name: "Mike", gender: "male"
index 1: name: "Jane", gender: "female"
index 2: name: "Ellen", gender: "female"
index 3: name: "Ben", gender: "male"
index 4: name: "Jimmy", gender: "male"
index 5: name: "Maria", gender: "female"

List B:

index 0: name: "Ben", gender: "male"
index 1: name: "Maria", gender: "female"
index 2: name: "Jane", gender: "female"
index 3: name: "Brian", gender: "male"
index 4: name: "Sofia", gender: "female"
index 5: name: "John", gender: "male"
index 6: name: "Jimmy", gender: "male"

I want to create a new list of names of all the males that is NOT in both lists.

So from the example the list would look like this:

index 0: name: "Mike", gender: "male"
index 1: name: "John", gender: "male"
index 2: name: "Brian", gender: "male"

The tricky things here is that the filtering goes both ways. I want the final list to contain both males that are in list A but not in list B, and males that are in list B but not in list A. I've not been able to find out how to do this, but I've tried to accomplish it using streams..

CodePudding user response:

not super efecient but works

List<Person> r =
  Stream.concat(
    a.stream().filter(e -> e.isMale() && !b.contains(e)),
    b.stream().filter(e -> e.isMale() && !a.contains(e))
  )
  .collect(Collectors.toList());

more readable versions with storing parial results

List<Person> aNotB = a.stream().filter(e -> e.isMale() && !b.contains(e)).collect(Collectors.toList());
List<Person> bNotA = b.stream().filter(e -> e.isMale() && !a.contains(e)).collect(Collectors.toList());
List<Person> r = new ArrayList<>(aNotB);
r.addAll(bNotA);

CodePudding user response:

List<String> malesNotInBothLists = listA.stream()
    .filter(p -> p.getGender().equals("male"))
    .filter(p -> !listB.stream().anyMatch(b -> b.getName().equals(p.getName())))
    .map(Person::getName)
    .collect(Collectors.toList());

malesNotInBothLists.addAll(listB.stream()
    .filter(p -> p.getGender().equals("male"))
    .filter(p -> !listA.stream().anyMatch(a -> a.getName().equals(p.getName())))
    .map(Person::getName)
    .collect(Collectors.toList()));`enter code here`
  • Related