Reputation: 3953
I am using Java8 to achieve the below things,
Map<String, String> m0 = new HashMap<>();
m0.put("x", "123");
m0.put("y", "456");
m0.put("z", "789");
Map<String, String> m1 = new HashMap<>();
m1.put("x", "000");
m1.put("y", "111");
m1.put("z", "222");
List<Map<String, String>> l = new ArrayList<>(Arrays.asList(m0, m1));
List<String> desiredKeys = Lists.newArrayList("x");
List<Map<String, String>> transformed = l.stream().map(map -> map.entrySet().stream()
.filter(e -> desiredKeys.stream().anyMatch(k -> k.equals(e.getKey())))
.collect(Collectors.toMap(e -> e.getKey(), p -> p.getValue())))
.filter(m -> !m.isEmpty())
.collect(Collectors.toList());
System.err.println(l);
System.err.println(transformed);
List<String> values = new ArrayList<>();
for (Map<String,String> map : transformed) {
values.add(map.values().toString());
System.out.println("Values inside map::"+map.values());
}
System.out.println("values::"+values); //values::[[123], [000]]
Here, I would like to fetch only the x-values from the list. I have achieved it but it is not in a proper format.
Expected output: values::[123, 000]
Actual output: values::[[123], [000]]
I know how to fix the actual output. But is there any easy way to achieve this issue? Any help would be appreciable.
Upvotes: 2
Views: 12669
Reputation: 1147
Flat map over the stream of maps to get a single stream representing the map entries of all your input maps. From there, you can filter out each entry whose key is not contained in the desired keys. Finally, extract the equivalent value of each entry to collect them into a list.
final List<String> desiredValues = l.stream()
.map(Map::entrySet)
.flatMap(Collection::stream)
.filter(entry -> desiredKeys.contains(entry.getKey()))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
EDIT
This assumes that if a map has the key "x" it must also has the key "y" so to fetch the corredponding value.
final List<String> desiredValues = l.stream()
.filter(map -> map.containsKey("x"))
.map(map -> map.get("y"))
.collect(Collectors.toList());
Upvotes: 3
Reputation: 28133
You do not need to iterate over the entire map to find an entry by its key. That's what Map.get
is for. To flatten the list of list of values, use flatMap
:
import static java.util.stream.Collectors.toList;
.....
List<String> values = l.stream()
.flatMap(x -> desiredKeys.stream()
.filter(x::containsKey)
.map(x::get)
).collect(toList());
On a side note, avoid using l
(lower case L) as a variable name. It looks too much like the number 1
.
Upvotes: 5
Reputation: 44338
I’m not sure Streams will help, here. It’s easier to just loop through the Maps:
Collection<String> values = new ArrayList<>();
for (Map<String, String> map : l) {
Map<String, String> copy = new HashMap<>(map);
copy.keySet().retainAll(desiredKeys);
values.addAll(copy.values());
}
Upvotes: 3