Java 8 Streams: Map the same object multiple times based on different properties

后端 未结 1 467
北海茫月
北海茫月 2020-12-13 13:54

I was presented with an interesting problem by a colleague of mine and I was unable to find a neat and pretty Java 8 solution. The problem is to stream through a list of POJ

相关标签:
1条回答
  • 2020-12-13 14:14

    I think your alternatives 2 and 3 can be re-written to be more clear:

    Alternative 2:

    Map<String, Customer> res2 = customers.stream()
        .flatMap(
            c -> Stream.of(c.first, c.last)
            .map(k -> new AbstractMap.SimpleImmutableEntry<>(k, c))
        ).collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
    

    Alternative 3: Your code abuses reduce by mutating the HashMap. To do mutable reduction, use collect:

    Map<String, Customer> res3 = customers.stream()
        .collect(
            HashMap::new, 
            (m,c) -> {m.put(c.first, c); m.put(c.last, c);}, 
            HashMap::putAll
        );
    

    Note that these are not identical. Alternative 2 will throw an exception if there are duplicate keys while Alternative 3 will silently overwrite the entries.

    If overwriting entries in case of duplicate keys is what you want, I would personally prefer Alternative 3. It is immediately clear to me what it does. It most closely resembles the iterative solution. I would expect it to be more performant as Alternative 2 has to do a bunch of allocations per customer with all that flatmapping.

    However, Alternative 2 has a huge advantage over Alternative 3 by separating the production of entries from their aggregation. This gives you a great deal of flexibility. For example, if you want to change Alternative 2 to overwrite entries on duplicate keys instead of throwing an exception, you would simply add (a,b) -> b to toMap(...). If you decide you want to collect matching entries into a list, all you would have to do is replace toMap(...) with groupingBy(...), etc.

    0 讨论(0)
提交回复
热议问题