Map.Entry methods for streams
Timo Kinnunen
timo.kinnunen at gmail.com
Fri Jan 15 19:02:54 UTC 2016
Hi,
For completeness, having also the methods
default <NK> Entry<NK, K> withKeyAsValue(NK newKey) {
return new AbstractMap.SimpleEntry<>(newKey, getKey());
}
public <NV> Entry<V, NV> withValueAsKey(NV newValue) {
return new AbstractMap.SimpleEntry<>(getValue(), newValue);
}
would be useful when inverting a graph, for example:
Map<A, List<B>> dag = //. . .
Map<B, List<A>> gad = dag.entrySet()
.stream()
.flatMap(e -> e.getValue().stream().map(e::withKeyAsValue))
.collect(groupingBy(Entry::getKey, mapping(Entry::getValue, toList())));
--
Have a nice day,
Timo
Sent from Mail for Windows 10
From: Peter Levart
Sent: Friday, January 15, 2016 16:44
To: Remi Forax; Stephen Colebourne
Cc: core-libs-dev
Subject: Re: Map.Entry methods for streams
Hi,
Another possibility would be to introduce the following default methods
to Map.Entry:
public interface Map.Entry<K, V> {
...
default <L> Map.Entry<L, V> withKey(L key) { ... }
default <W> Map.Entry<K, W> withValue(W value) { ... }
}
Usage would then look like:
map.entrySet().stream().map(e -> e.withValue(e.getValue().transformed()))
i.e. I don't think there's a need for function-taking methods like
mapKey/mapValue, because Map.Entry returning methods are not common in
APIs (Iterator<Map.Entry>.next() is a rare exception)...
Optional returning methods OTOH are common in APIs, so function-taking
methods on Optional are useful. Not so with Map.Entry, I think.
Regards, Peter
On 01/15/2016 02:37 PM, Remi Forax wrote:
> Hi Stephan,
> mixing methods that create a new entry (your mapValue) with one that mutate the current entry (setValue) is still a bad idea.
>
> I think it's better to introduce a static method in Map.Entry like this:
> public static <K, V, R> Function<Map.Entry<K, V>, Map.Entry<K, R>> mapValue(Function<? super V, ? extends R> valueMapper) {
> return entry -> Map.entry(entry.getKey(), valueMapper.apply(entry.getValue()));
> }
>
> and use it like this:
> map.entrySet().stream().map(mapValue(v -> v.transformed))
>
> Also with the introduction of Map.entry() in 9, your "not really pleasant example" is a little better
> map.entrySet().stream().map(e -> entry(e.getKey(), e.getValue.transformed()))
>
> regards,
> Rémi
>
> PS: in 9, you can use Map.entry() instead of new AbstractMap.SimpleImmutableEntry<>().
>
> ----- Mail original -----
>> De: "Stephen Colebourne" <scolebourne at joda.org>
>> À: "core-libs-dev" <core-libs-dev at openjdk.java.net>
>> Envoyé: Vendredi 15 Janvier 2016 14:05:51
>> Objet: Map.Entry methods for streams
>>
>> I've had a morning of discussion about streaming Map this morning. While
>> there is clearly no appetite for a JDK MapStream right now, it does seem
>> that two additional methods on Map.Entry could help.
>>
>> Two of the common cases when streaming over Map.Entry are to transform the
>> keys and to transform the values. Currently, the code is as follows:
>>
>> hashMap.entrySet().stream()
>> .map(e -> new AbstractMap.SimpleImmutableEntry(e.getKey(),
>> e.getValue().transformed()))
>> ...
>>
>> This isn't really very pleasant.
>>
>> Adding a default method to Map.Entry would help:
>>
>> hashMap.entrySet().stream()
>> .map(e -> e.mapValue(v -> v.transformed()))
>> ...
>>
>> Implementation of the mapValue method is left to the reader, but it isn't
>> hard. A mapKey() method would also be needed. Note that both are designed
>> to work without mutating the map (returning a new entry).
>>
>> Finally, the Collectors class could do with a new method entriesToMap()
>> that collects a stream of Map.Entry back into a Map.
>>
>> While these proposals are not as powerful as a MapStream, they would smooth
>> some rough edges in the API when working with maps.
>>
>> Stephen
>>
More information about the core-libs-dev
mailing list