spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

Introduce static `MultiValueMap` factory methods

Open poutsma opened this issue 1 year ago • 1 comments

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>>)

poutsma avatar May 16 '24 08:05 poutsma

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<K, V> MultiValueMap::of(Map<K, V>), 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?

xenoterracide avatar May 16 '24 19:05 xenoterracide

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

poutsma avatar May 24 '24 09:05 poutsma