Java 9 introduced static factory methods on the collection interaces, to create immutable collections. We should consider doing the same for MultiValueMap.

There are several open questions to answer: * Should multi-value maps returned by these factory methods be immutable, just like the java collections? * It seems difficult to create a convenient, unambiguous API that takes keys and values. Consider MultiValueMap.of("foo", "bar", "baz", "qux"). Does the resulting map have two entries (foo->bar and baz->qux)? Or does it have one entry, with three values (foo->[bar, baz, qux])? Without reading the javadoc, you would not know, which makes the method problematic. * We could introduce MultiValueMap<K, V> MultiValueMap::of(Map<K, V>), so that you could do MultiValueMap.of(Map.of("foo", "bar"). * If we also want to support multiple values, we could have MultiValueMap<K, V> MultiValueMap::of(Map<K, List<V>>), which allows MultiValueMap.of(Map.of("foo", List.of("bar", "baz")). * If we want to support both of variants (single and multi value), they would have to be named differently because of type erasure. For instance, MultiValueMap<K, V> MultiValueMap::ofSingle(Map<K, V>) and MultiValueMap<K, V> MultiValueMap::ofMulti(Map<K, List<V>>)

Comment From: xenoterracide

It seems difficult to create a convenient, unambiguous API that takes keys and values. Consider MultiValueMap.of("foo", "bar", "baz", "qux"). Does the resulting map have two entries (foo->bar and baz->qux)? Or does it have one entry, with three values (foo->[bar, baz, qux])? Without reading the javadoc, you would not know, which makes the method problematic.

I think I would add this, but not call it of rather something like ofKeyValues, although if you go with java's way... that would result in "foo->bar and baz->qux, but you could get the latter by doing "foo", "bar", "foo", "baz", "foo", "qux" although I think that java has a limit to this telescoping constructor, so diminishing returns.

We could introduce MultiValueMap MultiValueMap::of(Map), so that you could do MultiValueMap.of(Map.of("foo", "bar").

also a good idea

I think I would probably have

  • MultiValueMap<K, V> MultiValueMap::of(Map<K, List<V>>)
  • MultiValueMap<K, V> MultiValueMap::ofMap(Map<K, V>)

the ofMap or ofSingle feels like it probably covers the other case well enough. If later the other needs to be added, it still could. I'm not certain about simply ofSingle as a name... intuitively I'm not certain would would think of this as each key only having a single value.

ofSingle feels like of singleton, or maybe foo->[bar, baz, qux]) where ofMulti is foo->bar and baz->qux or maybe it's the other way around... lol. of single value? of single key?

Comment From: poutsma

In the end, we settled for fromMultiValue and fromSingleValue, so that you can write fromSingleValue(Map.of("foo", "bar")), which reads rather nicely.