Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
184 views
in Technique[技术] by (71.8m points)

Transform and filter a Java Map with streams

I have a Java Map that I'd like to transform and filter. As a trivial example, suppose I want to convert all values to Integers then remove the odd entries.

Map<String, String> input = new HashMap<>();
input.put("a", "1234");
input.put("b", "2345");
input.put("c", "3456");
input.put("d", "4567");

Map<String, Integer> output = input.entrySet().stream()
        .collect(Collectors.toMap(
                Map.Entry::getKey,
                e -> Integer.parseInt(e.getValue())
        ))
        .entrySet().stream()
        .filter(e -> e.getValue() % 2 == 0)
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));


System.out.println(output.toString());

This is correct and yields: {a=1234, c=3456}

However, I can't help but wonder if there's a way to avoid calling .entrySet().stream() twice.

Is there a way I can perform both transform and filter operations and call .collect() only once at the end?

question from:https://stackoverflow.com/questions/35486826/transform-and-filter-a-java-map-with-streams

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, you can map each entry to another temporary entry that will hold the key and the parsed integer value. Then you can filter each entry based on their value.

Map<String, Integer> output =
    input.entrySet()
         .stream()
         .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), Integer.valueOf(e.getValue())))
         .filter(e -> e.getValue() % 2 == 0)
         .collect(Collectors.toMap(
             Map.Entry::getKey,
             Map.Entry::getValue
         ));

Note that I used Integer.valueOf instead of parseInt since we actually want a boxed int.


If you have the luxury to use the StreamEx library, you can do it quite simply:

Map<String, Integer> output =
    EntryStream.of(input).mapValues(Integer::valueOf).filterValues(v -> v % 2 == 0).toMap();

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...