6

I'm wondering why the Java Collections API doesn't contain handy map methods on the different collection types. I would like to write something like:

List<Foo> list = ...;    
List<String> result = list.map(Foo::toString);

Instead I have to create a stream, map and collect, like this:

List<Foo> list = ...; 
List<String> result = list.stream().map(Foo::toString).collect(toList());

Wouldn't it be as easy as implementing this default method in the java.util.List interface? E.g.

default <R> List<R> map(Function<E, R> mapper){
    return stream().map(mapper).collect(Collectors.toList());
}

On first sight, it seems like other convenients methods are in place. For example:

list.stream().forEach(x -> {});

can be written as

list.forEach(x -> {});

However, the comparision is not that good. Iteratable.forEach is a default method on the top level interface and doesn't need to specify a return type. It's not creating a stream under the hood, but rather using Iteratables properties to... well... iterate all elements.

So the question remains: Why not have a map method on each and every Collections API interface? Maybe because it's not flexible enough because you would need to decide on a return type?

I'm sure the implementors thought about it and had their reasons to not put it in. And I would like to understand why.

Tim Büthe
  • 62,884
  • 17
  • 92
  • 129
  • Just four days earlier: [“Why does `List` not have a `map` default method when it has `forEach`?”](http://stackoverflow.com/q/42364761/2711488) – Holger Feb 27 '17 at 10:35

1 Answers1

7

Yes, this is deliberate. Some reasons I've heard discussed:

  • many times, these methods are chained together, in which case it's more efficient to only collect into an explicit data structure at the end of the computation
  • control the absolute size of the interface; manage the number of options appearing in autocomplete
  • avoid conflicts with outside implementations of Collection that already provided methods named map, etc.
  • build all the fluent features into one coherent API with specialized configuration methods like parallel(); and that API can now be evolved separately from the collections it's built on
  • as you mentioned, let the user explicitly decide on an implementation of the return type -- if you had an arbitrary Collection and called map on it, it could either be a List, or a Set that silently deduplicates its output?! that'd be super confusing
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413