[英]Remove all entries where value is an empty Optional from map
我想从地图中删除value为空的所有条目。 看起来似乎并不复杂,但我试图找到一个更好的解决方案。
输入:
我有以下地图:
Map<String, Function<String, Optional<String>>> attributesToCalculate = new HashMap<>();
其中key - 只是一个String和value - 对返回Optional <String>的方法的引用
输出:
结果,我想得到
Map<String, String> calculatedAttributes
(不包括值为空的条目可选)
这是我的解决方案
return attributesToCalculate.entrySet()
.stream()
.map(entry -> Pair.of(entry.getKey(), entry.getValue().apply(someString)))
.filter(entry -> entry.getValue().isPresent())
.collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().get()));
但是我不喜欢.filter部分因为那时我必须在collect部分中的Optional上调用.get() 。
是否有更好的方法(可能没有.get调用)来解决这个问题? 谢谢。
如上所述,如果您已经检查过Optional
不为空,则使用get
没有任何问题。
但是,我认为这段代码最好不使用流表达。
Map<String, String> result = new HashMap<>();
attributesToCalculate.forEach((k, v) ->
v.apply(someString).ifPresent(str -> result.put(k, str))
);
如果您不喜欢使用forEach
以这种方式填充地图,则可以使用简单的for
循环。
使用Guava,您可以这样做:
Maps.filterValues(
Maps.transformValues(
attributesToCalculate,
f -> f.apply("someString").orElse(null)),
Predicates.notNull())
请注意,这将返回基础映射的视图,这意味着任何查找或迭代都将委托给该函数。 如果这是一个问题,只需将结果复制到新地图。
或者您可以考虑StreamEx的EntryStream
:
EntryStream.of(attributesToCalculate)
.mapValues(f -> f.apply("someString"))
.flatMapValues(StreamEx::of)
.toMap();
不是一个非常漂亮的,类似于for循环:
return attributesToCalculate.entrySet().stream().collect(HashMap::new, (sink, entry) -> {
entry.getValue().apply(someString).ifPresent(v -> sink.put(entry.getKey(), v));
}, Map::putAll);
您可以定义一个辅助方法来创建您的Pair:
public static <L, R> Optional<Pair<L, R>> of2(L left, Optional<R> right) {
return right.map(r -> Pair.of(left, r));
}
虽然这意味着使用Optional作为参数,但在这种情况下它不是那么糟糕的imo(如果你内联方法,你不会把它作为参数...)。
然后你可以这样做:
attributesToCalculate.entrySet()
.stream()
.map(entry -> of2(entry.getKey(), entry.getValue().apply(someString)))
.flatMap(Optional::stream) // Java 9
.collect(Collectors.toMap(Map.Entry::getKey, Pair::getValue));
使用普通的旧Iterator
什么问题? 这看起来并不像其他一些流解决方案那么冗长。
final Map<String, Optional<Object>> attributesToCalculate = new HashMap<>();
final Map<String, Object> calculatedAttributes = new HashMap<>();
final Iterator<Entry<String, Optional<Object>>> iter = attributesToCalculate.entrySet().iterator();
while (iter.hasNext()) {
final Entry<String, Optional<Object>> current = iter.next();
if (current.getValue().isPresent()) {
calculatedAttributes.put(current.getKey(), current.getValue().get());
}
}
或者使用plain for循环更短:
for(Entry<String, Optional<Object>> current : attributesToCalculate.entrySet()) {
if (current.getValue().isPresent()) {
calculatedAttributes.put(current.getKey(), current.getValue().get());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.