using a stream based on the content of Optional<Map>

冷暖自知 提交于 2019-12-22 06:46:44

问题


I get a map from a service not under my control that might be null and want to process it, let's say, filter, map and reduce to a single element I need.

Question: is there a "link" from Optional to Stream?

I tried (among other things):

 return Optional.ofNullable(getMap())
   .map(Map::entrySet) // gets the entryset
   .map(Stream::of)
   .orElseGet(Stream::empty)
   // i would then like to continue with
   .filter(e -> e.getKey().startsWith("f")
   .map(Entry::getValue)
   .findFirst();

but then I get not Stream<Entry> but Stream<Set<Entry>> ... is there a way to somehow flatMap a collection or map out of an Optional?

Note: I am interested in a fluent, pure stream/optional approach here. It works of course when I save the map to local var first and make sure it is not null.


回答1:


Your mistake is in this line:

.map(Stream::of)

The of function takes a single parameter (or a vararg parameter), and returns a stream with only that element. You will therefore get a Stream<Set<Map.Entry>>. Instead, you should call the stream method on the entryset, like this:

.map(Set::stream)



回答2:


I think I'm going to answer the question.

 return Optional.ofNullable(getMap())
   .map(Map::entrySet) // gets the entryset
   .map(Stream::of)
   .orElseGet(Stream::empty)
   // i would then like to continue with
   .filter(e -> e.getKey().startsWith("f")
   .map(Entry::getValue)
   .findFirst();

I'm sick, really sick when I saw above code. Is it really so important for you write code in fluent approach, instead of writing simple code? first of all, as @ Didier L mentioned in the comments, it's wrong way to use Optional. Secondly, the code is so hard to read, isn't it? if you write it with defining a local variable:

Map<String, Integer> map = getMap();

return map == null ? Optional.<Integer> empty() 
                   : map.entrySet().stream()
                        .filter(e -> e.getKey().startsWith("f")).map(Entry::getValue).findFirst();

Isn't it much clear? Or you can do it with StreamEx if you can't get over not using fluent approach:

StreamEx.ofNullable(getMap())
        .flatMapToEntry(Function.identity())
        .filterKeys(k -> k.startsWith("f")).values().findFirst();

Or my library AbacusUtil

EntryStream.of(getMap()).filterByKey(k -> k.startsWith("f")).values().first();

Always trying to look for a better approach if things are stuck.



来源:https://stackoverflow.com/questions/44567806/using-a-stream-based-on-the-content-of-optionalmap

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!