9

I want to transform a List<String> into a Map<String, Integer>. The lists' values should serve as keys, and the map value will be statically initialized.

I want to keep the order of the list, thus using a LinkedHashMap, and ignore duplicates.

Question: is there any advantage using the java8 stream API? Because, comparing the following, simply regarding the syntax I'd never go for the verbose stream api, but always sticking to the old foreach loop:

    //foreach
    Map<String, Integer> map = new LinkedHashMap<>();
    for (String k : abk) {
        if (k != null) map.put(k, STATIC_VAL);
    }

    //streams
    Map<String, Integer> map2 = abk.stream()
            .filter(Objects::nonNull)
            .collect(Collectors.toMap(
                        Function.identity(),
                        k -> STATIC_VAL,
                        (v1, v2) -> v1,
                        LinkedHashMap::new));

Would you stick to the old approach or go with new lambda expressions?

4
  • What do you mean "ignore duplicates"? Duplicates will be removed, not ignored. Commented Jul 6, 2017 at 9:19
  • I mean I don't want to throw an exception on duplicate keys. Because the map is initialized with a static value, I don't care for duplicate keys. Commented Jul 6, 2017 at 9:20
  • 3
    OK. Well, anyway, I don't subscribe to the streams religion. If you have a more readable traditional loop and no need for parallelizing, use a traditional loop. Commented Jul 6, 2017 at 9:21
  • It seems strange to me that you would map all the keys to the same value. Just a guess, but are you trying to initialize a counter to zero? If so, you may find the getOrDefault method that's been added to Map to be quite useful. Commented Jul 7, 2017 at 11:32

3 Answers 3

8

For this simple case I would stick to the for loop. It is faster too by the way (besides being more readable), Streams do have a cost of the infrastructure that has to be used. This new API is just a tool and as every tool is has pros/cons.

Generally I tent to used stream api only when I have to - let's say that the List needs filtered or mapped to something else, etc - then the Stream usage would make sense. If there are multiple operations that have to be done, it would make code way more readable then doing the same thing with a loop; but that's not always the case - as in your example.

Parallelization (in case you really need it is another aspect). Simple for loops are not easily parallelized, but with streams this is a breeze.

4

There's a variant on the traditional for loop that you can use as well:

Map<String, Integer> map = new LinkedHashMap<>();
abk.forEach(k -> if (k != null) map.put(k, STATIC_VAL));

But it's just a matter of style. Either this way or the traditional for loop looks good to me. Using streams, on the other hand, is more verbose and less readable, IMO.

2

You could write the for-each with stream. eg.

abk.stream()
    .filter(Object::notNull)
    .forEach(s->map.put(s, STATIC_VAL));

Not the answer you're looking for? Browse other questions tagged or ask your own question.