How can I simplify this code into a single lambda expression? The idea is that there is a list of maps and I would like to create a new list of maps, using a filter on the key. In this example, I want to remap it so that it only keeps the keys "x" and "z".
Map<String, String> m0 = new LinkedHashMap<>();
m0.put("x", "123");
m0.put("y", "456");
m0.put("z", "789");
Map<String, String> m1 = new LinkedHashMap<>();
m1.put("x", "000");
m1.put("y", "111");
m1.put("z", "222");
List<Map> l = new ArrayList<>(Arrays.asList(m0, m1));
List<Map> tx = new ArrayList<>();
for(Map<String, String> m : l) {
Map<String, String> filtered = m.entrySet()
.stream()
.filter(map -> map.getKey().equals("x") || map.getKey().equals("z"))
.collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
tx.add(filtered);
}
System.err.println("l: " + l);
System.err.println("tx: " + tx);
Output:
l: [{x=123, y=456, z=789}, {x=000, y=111, z=222}]
tx: [{x=123, z=789}, {x=000, z=222}]
Java 8 Stream's map method is intermediate operation and consumes single element forom input Stream and produces single element to output Stream. It simply used to convert Stream of one type to another. Let's see method signature of Stream's map method.
List Listofvalues= map.collect(Collectors. toCollection(ArrayList::new)); Note: You can collect elements of Stream in an ArrayList, LinkedList, or any other List implementation.
Method 1: Using Collectors.toMap() Function The Collectors. toMap() method takes two parameters as the input: KeyMapper: This function is used for extracting keys of the Map from stream value. ValueMapper: This function used for extracting the values of the map for the given key.
Of course, you can convert your entire operation into one Stream operation.
// no need to copy a List (result of Array.asList) to an ArrayList, by the way
List<Map<String, String>> l = Arrays.asList(m0, m1);
List<Map<String, String>> tx = l.stream().map(m -> m.entrySet().stream()
.filter(map -> map.getKey().equals("x") || map.getKey().equals("z"))
.collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue())))
.collect(Collectors.toList());
But note that streaming over a Map
and filtering is an operation with a linear time complexity, as it will check each key of each map against the filter, while you have only a very small number of actual keys you want to retain. So here, it is much simpler and more efficient (for larger maps) to use
List<Map<String, String>> tx = l.stream()
.map(m -> Stream.of("x", "y")
.filter(m::containsKey).collect(Collectors.toMap(key->key, m::get)))
.collect(Collectors.toList());
which will only perform four lookups per map. If it bothers you, you could even reduce it to two lookups, however, the constant factor is irrelevant for the overall time complexity, which will be constant time, if the map has a constant time lookup, like HashMap
. Even for map’s with O(log(n))
lookup time complexity, like TreeMap
, this will be more efficient than the linear scan, if the maps are larger than the three mappings of the example code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With