如何使用Java Stream重构枚举生成Map的方法?
问题描述
我定义了如下枚举类:
public enum MyEnum { A("A"), B("B"); private final String key; }
我原本通过以下方法生成Map:
private Map<MyEnum, MyClass> myMethod(String input) { Map<MyEnum, MyClass> result = Maps.newHashMap(); for (MyEnum enum : MyEnum.values()) { Optional<MyClass> value = helper(enum, input); value.ifPresent(val -> result.put(enum, val)); } return result; }
我刚接触Lambda/Stream,希望将其重构为类似以下的形式:
private Map<MyEnum, MyClass> myMethod(String input) { return MyEnum.values().stream().map(...).collect(Collector.toMap(...)); }
我尝试使用Arrays.stream()...,但在调用collect(Collector.toMap(Map.Entry::getKey, Map.Entry::getValue)时遇到了静态与非静态的问题,请问该如何解决?
解决方案
不用绕弯子转成Map.Entry再处理,直接用Stream的过滤和收集就能搞定,还能避免空值问题:
写法一(仅调用一次helper,效率更高)
private Map<MyEnum, MyClass> myMethod(String input) { return Arrays.stream(MyEnum.values()) // 将枚举值与对应的Optional结果打包成Entry .map(enumVal -> Map.entry(enumVal, helper(enumVal, input))) // 过滤掉结果为空的Entry .filter(entry -> entry.getValue().isPresent()) // 收集为Map,取出Optional中的实际值 .collect(Collectors.toMap( Map.Entry::getKey, entry -> entry.getValue().get() )); }
写法二(更简洁,适合helper调用成本低的场景)
private Map<MyEnum, MyClass> myMethod(String input) { return Arrays.stream(MyEnum.values()) // 先过滤出helper能返回非空结果的枚举值 .filter(enumVal -> helper(enumVal, input).isPresent()) // 直接收集,键为枚举值本身,值为Optional中的实际对象 .collect(Collectors.toMap( Function.identity(), enumVal -> helper(enumVal, input).get() )); }
问题原因说明
你之前遇到的静态非静态问题,是因为Map.Entry::getKey和Map.Entry::getValue是实例方法,必须依托合法的Map.Entry实例才能使用方法引用。之前的写法要么没正确生成Entry实例,要么引用方式有误,导致报错。
另外补充:MyEnum.values()返回的是数组,所以需要用Arrays.stream()(或Stream.of(MyEnum.values()))转换成流才能使用Stream API。
内容的提问来源于stack exchange,提问作者cnmdestroyer
相关产品推荐
相关产品推荐

