0

I've got a list of Person objects like this:

list.add(new Person("John", 20)); //person is just name and age
list.add(new Person("Maria", 21));
list.add(new Person("John", 40));
list.add(new Person("Carl", 10));

The resulting list must have no persons with the same name, regardless of age, so only 3 elements would survive. How can this be accomplished using Java 8 lambda expressions?

CCC
  • 2,642
  • 7
  • 40
  • 62

4 Answers4

2

You can try the following:

Set<String> unique = new HashSet<>();
list.removeIf(e -> !unique.add(e.getName()));

Note, that the Person class needs to have a getter to return the name of the person.

VHS
  • 9,534
  • 3
  • 19
  • 43
0

Overwrite the hashCode() and equals(). Then you can use this:

List<Person> collect = list.stream().distinct().collect(Collectors.toList());
chaos
  • 1,359
  • 2
  • 13
  • 25
  • 1
    distinct here would apply to the object, not to the name itself.. – CCC Mar 15 '18 at 03:01
  • 2
    That's probably why he suggests to overwrite `equals` and `hashCode` with the corresponding logic (two persons are equal iff they have the same name). – Zabuzard Mar 15 '18 at 04:16
  • yes, but that's a pretty bad practice. Saying an object is equals to another object just based on a single attribute and not the rest is bad design only intended for a particular scenario. – CCC Mar 15 '18 at 15:00
0

Turn the list into a map in which they key is Person::getName and the value is the object itself, and if they are equal choose the first one, then get the map values which is a Collection, and lastly convert to a List

list = list.stream().collect(Collectors.toMap(Person:getName, Function.Identity(), 
(a, b) -> a)).values().stream().collect(Collections.toList());
CCC
  • 2,642
  • 7
  • 40
  • 62
0

This could easily be done using Comparator. As this is really flexible to use and also allows multiple comparison criteria as per your need. See code below:-

    Set<Person> expectedOutput = new TreeSet<>((person1, person2) ->
            person1.getName().equals(person2.getName()) ? 0 : 1
    );
    list.listIterator().forEachRemaining(expectedOutput::add);

I personally will avoid overriding equals for a fluctuating criteria. For example, If i say that my objects are equal if names are equal in one scenario and in other scenario I say my objects are equal if ages are equal. Then it's better to use comparator.

Vinay Prajapati
  • 7,199
  • 9
  • 45
  • 86