VelNaga
VelNaga

Reputation: 3953

Java8 convert List of Map to List of string

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

Answers (3)

marsouf
marsouf

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

Misha
Misha

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

VGR
VGR

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

Related Questions