Basically I look for a way to avoid working with
entry -> entry.getValue
and
entry -> entry.getKey
similar to what Map.forEach()
does.
If only I could get a way to work as map.stream().filter((k,v) -> )
... and so on
It seems the interface is called BiConsumer. Perhaps with a converter to BiConsumer or a Stream.generate() someway
No, there's no way to do this;
Stream
only works with a single element type. There's no way around thegetKey
andgetValue
approach.(Streaming over the keys and calling
get
doesn't actually seem to be any better from your perspective, and it's likely to be strictly less efficient.)Since this is a repeating question, I will throw a full solution into the ring. It’s a
PairStream
type that is by default a simple wrapper around an ordinaryStream
(though, being aninterface
, alternatives are possible).It focuses on providing the convenient intermediate operations and those terminal operations which can not be easily performed by calling one of the methods
keys()
,values()
orentries()
to return to a conventional single-elementStream
and chain a terminal operation. So for example,PairStream.from(map).filterValue(predicate).keys().findAny()
is the straight-forward way to get a key for which the mapped value matches the predicate.filterValue
is a convenience intermediate operation andkeys
turn back to an ordinaryStream
allowing an arbitrary terminal operation for the keys.Some examples
Here is the complete class (I haven’t tested all operations, however most of it is straight-forward):
It's a bit unfortunate that the main way to process a map using streams is to stream the map's entries. That means you have to extracting the entries' keys and values. This is somewhat verbose, but it isn't really all that bad. Still, it might be reasonable to consider some kind of helper methods that will adapt a
BiPredicate
orBiFunction
so that they can be used in thefilter
ormap
stages of a stream of map entries. They look like this:Once you have these, you can use them to simplify(?) a map entry stream. Let's say you have a
Map<String,Integer>
and you want to select the entries where the string key's length is greater than the integer value, and then format the key and value into a string. Conventionally you'd do this:With the helper functions above, you could rewrite this pipeline as:
OK, you save a few characters. Is it worth it?