Convert String array to Map using Java 8 Lambda expressions
Asked Answered
P

1

61

Is there a better functional way of converting an array of Strings in the form of "key:value" to a Map using the Java 8 lambda syntax?

Arrays.asList("a:1.0", "b:2.0", "c:3.0")
        .stream()
        .map(elem -> elem.split(":")
        .collect(Collectors.toMap(keyMapper?, valueMapper?));

The solution I have right now does not seem really functional:

Map<String, Double> kvs = new HashMap<>();
Arrays.asList("a:1.0", "b:2.0", "c:3.0")
        .stream()
        .map(elem -> elem.split(":"))
        .forEach(elem -> kvs.put(elem[0], Double.parseDouble(elem[1])));
Platto answered 29/7, 2015 at 7:21 Comment(0)
H
96

You can modify your solution to collect the Stream of String arrays into a Map (instead of using forEach) :

Map<String, Double> kvs =
    Arrays.asList("a:1.0", "b:2.0", "c:3.0")
        .stream()
        .map(elem -> elem.split(":"))
        .collect(Collectors.toMap(e -> e[0], e -> Double.parseDouble(e[1])));

Of course this solution has no protection against invalid input. Perhaps you should add a filter just in case the split String has no separator :

Map<String, Double> kvs =
    Arrays.asList("a:1.0", "b:2.0", "c:3.0")
        .stream()
        .map(elem -> elem.split(":"))
        .filter(elem -> elem.length==2)
        .collect(Collectors.toMap(e -> e[0], e -> Double.parseDouble(e[1])));

This still doesn't protect you against all invalid inputs (for example "c:3r" would cause NumberFormatException to be thrown by parseDouble).

Heir answered 29/7, 2015 at 7:24 Comment(9)
I don't think that silently ignoring erroneous input is a good advice and this was not requested by OP. I'd better use elem -> elem.split(":", 2) instead of adding the filter step. This way erroneous input will be manifested either by ArrayIndexOutOfBoundsException (if no colon was found) or by NumberFormatException (if more than one colon was found).Themis
Thanks for all the comments and additional input on the error checking. This is what I needed.Platto
If task is to convert a real array to Map, then the expression should start with Arrays.stream(<arrayVariable>)Ornate
@Ornate It also works with the current code - Arrays.asList(<arrayVariable>).stream().... The Arrays.asList("a:1.0", "b:2.0", "c:3.0") part was taken as is from the question.Heir
@Heir Arrays.asList() returns a List. Someone may have a real array.Ornate
@Ornate It returns a List, but it accepts an array.Heir
@Heir I got your point, but Arrays.stream(<array>) is shorter anyway. And fits better the subject of the question. Peace. :)Ornate
Missing closing parenthesis.Fellatio
@Fellatio that was careless of me. Thanks again!Heir

© 2022 - 2024 — McMap. All rights reserved.