Let's say I have a list of names:
List<String> names = new ArrayList<>();
names.add("Paul");
names.add("Jeff");
names.add("Anna");
On the other hand, I have a list of people:
List<Person> people = new ArrayList<>();
people.add( new Person("Paul", 30) );
people.add( new Person("Jeff", 50) );
Person has name and age attributes. From the first list of names, I need to know what names are not present as names in the list of people. This is my attempt:
List<String> namesNotPresent = new ArrayList<>();
for (String name : names) {
boolean nameNotPresent = people.stream()
.noneMatch(p -> name.equals(p.getName()));
if (nameNotPresent) {
namesNotPresent.add(name);
}
}
I wonder if there is a better approach, a more functional one, and I also wonder if the list of people should be ordered?
This is working for me though. I don't expect the list of names and people to be a huge list, there might be exceptions where they could have around 1000 items though.
CodePudding user response:
A better approach would be to use some kind of Map
, such as a HashMap<String,Person>
to store the Person
objects, indexed by name. That way, you're not iterating through the list to find each name.
Map<String,Person> personsByName = new HashMap<>();
personsByName.put( "Paul", new Person("Paul", 30));
personsByName.put( "Jeff", new Person("Jeff", 50));
names.removeIf(name->personsByName.contains(name));
Note that this removes things from names
- if you want to keep this list, make a copy first.
CodePudding user response:
You don't need to stream over your people
list for each name in your names
list.
List<String> namesNotPresent = new ArrayList<>(names);
namesNotPresent.removeAll(people.stream().map(Person::getName).collect(Collectors.toList()));
CodePudding user response:
public List<String> findNameNotPresent(List<String> names, List<Person> people) {
List<String> result = new ArrayList<>(names);
people.stream()
.map(Person::getName)
.forEach(result::remove);
return result;
}
CodePudding user response:
You are looking for a more functional approach. Functional means side effects must be avoided. This is a functional approach:
List<String> pnames = people.stream().map(Person::getName).toList();
List<String> namesNotPresent = names.stream().filter(n -> !pnames.contains(n)).toList();
Prior to Java 17 you would have to substitute toList()
by collect(Collectors.toList())
.