Heineken
Heineken

Reputation: 21

Get map entries with matching keys using Stream API

I have an array of values

String [] str = { ONE, TWO, THREE };

and some key-value pairs stored in a map

Map<String, String> map;

How can I use the Stream API to get all entries from the map whose key is contained in the array?

Upvotes: 2

Views: 2795

Answers (4)

fps
fps

Reputation: 34460

One way is to stream the array and collect the elements into a new map, with the keys being the elements and the values taken from your map for each key:

Map<String, String> result = Arrays.stream(str)
    .collect(Collectors.toMap(e -> e, map::get));

This assumes all the elements of the array are keys in the map, and no duplicate elements on the array.

If you want to filter out elements that aren't keys of the map, use filter on the stream:

Map<String, String> result = Arrays.stream(str)
    .filter(map::containsKey)
    .collect(Collectors.toMap(e -> e, map::get));

And if you have duplicate elements in the array:

Map<String, String> result = Arrays.stream(str)
    .filter(map::containsKey)
    .collect(Collectors.toMap(e -> e, map::get, (o, n) -> o));

The last parameter (o, n) -> o is a merge function that is applied to values when there are duplicates keys on the map. In this case, the merge function keeps the old value and discards the new one.

Upvotes: 1

Holger
Holger

Reputation: 298143

You didn’t specify the form of the result.

If you want the same map but only containing the specified keys, you can use

Map<String, String> map;
Map<String, String> result = new HashMap<>(map);
result.keySet().retainAll(Arrays.asList(str));

If the old state is not needed anymore and the map is mutable, you may apply the second statement to the map without creating a copy.

A solution always creating a new Map would be

Map<String, String> result = Arrays.stream(str)
    .collect(HashMap::new, (m, k) -> m.computeIfAbsent(k, map::get), Map::putAll);

If you just want an array containing values corresponding to the array containing the keys, you could use

String[] result = new String[str.length];
Arrays.setAll(result, ix -> map.get(str[ix]));

or

String[] result = Arrays.stream(str).map(map::get).toArray(String[]::new);

Upvotes: 1

erickson
erickson

Reputation: 269667

If the map and the set of keys to remove are small, start with a copy of the map, and then modify it.

Map<String, String> filtered = new HashMap<>(map);
filtered.keySet().retainAll(Arrays.asList(str));

If the map is so much larger than the set of keys to remove that making a copy is undesirable, you can build a new map with only the correct entries:

Set<String> filter = new HashSet<>(Arrays.asList(str));
Map<String, String> filtered = map.entrySet().stream()
    .filter(e -> filter.contains(e.getKey))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

Upvotes: 1

eric.v
eric.v

Reputation: 615

I assume that when you say you want the entries from this map, you mean the values so here is how I would do it

    String[] str = {"ONE", "TWO", "THREE"};
    Map<String, String> map = <Your map's here>;

    List<String> values = Stream.of(str)
            .filter(map::containsKey)
            .map(map::get)
            .collect(Collectors.toList());

Upvotes: 1

Related Questions