user7950856
user7950856

Reputation:

Filtering a map based on a list of keys

I have a map like the following:

class Person {

    Long personId;
    String name;

    /*Getters and Setters*/
}

I have populated a map Map<Long, Person> personMap = new HashMap<>();

The key of the map is the personId itself. I have a list of personIds like so,

List<Long> coolPeople = new ArrayList<>();

now I want to iterate through the map and get all the values with the keys corresponding the ids in the list coolPeople, and then store it in a List.

How can I achieve this in Java 8 optimally?

Upvotes: 14

Views: 36903

Answers (5)

jcvalverde
jcvalverde

Reputation: 398

I found this question looking for a way to filter the entries in a map using stream() and after reading the current answers I feel like this one is missing:

Map<String, String> result = myMap.entrySet().stream()
                .filter(entry -> { /* apply conditions for entry.getKey() and entry.getValue() here */})
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Upvotes: 5

Adam Morawski
Adam Morawski

Reputation: 59

If you are interested in returning a map, you could use the following:

public static <K, V> Map<K, V> filterByKeys(final Map<K, V> map, final Iterable<K> keys) {
    final Map<K, V> newMap = new HashMap<>();
    keys.forEach(key -> Optional.ofNullable(map.get(key))
            .ifPresent(value -> newMap.put(key, value)));
    return newMap;
}

Upvotes: 1

Luatic
Luatic

Reputation: 11201

Correct this :

List<Long> coolPeople = new ArrayList();

and for the other part :

List<Person> coolPersons=new ArrayList<Person>();
for (Long id:coolPeople) {
     Person p=map.get(id);
     coolPersons.add(p);
}

Feel free to comment if you are having any questions.

Upvotes: -2

Eran
Eran

Reputation: 394096

It would be more efficient to iterate over the identifiers of the List and look them up in the Map, since search by key in a HashMap takes expected O(1) time, while the search in the List can take O(n) time at the worst case.

List<Person> people = 
    coolPeople.stream()
              .map(id -> personMap.get(id)) // or map(personMap::get)
              .filter(Objects::nonNull)
              .collect(Collectors.toList());

Upvotes: 17

assylias
assylias

Reputation: 328855

An alternative solution (and possibly more efficient - depending on the size of the map / list) would be to copy the map and act on the keySet directly:

Map<Long, Person> copy = new HashMap<> (personMap);
copy.keySet().retainAll(coolPeople);

Collection<Person> result = copy.values();

Upvotes: 10

Related Questions