Joe*_*oel 5 java java-8 java-stream
假设我有一些流,想收集到这样的地图
stream.collect(Collectors.toMap(this::func1, this::func2));
Run Code Online (Sandbox Code Playgroud)
但我想跳过空键/值.当然,我可以这样做
stream.filter(t -> func1(t) != null)
.filter(t -> func2(t) != null)
.collect(Collectors.toMap(this::func1, this::func2));
Run Code Online (Sandbox Code Playgroud)
但是有更美观/有效的解决方案吗?
如果要避免评估函数func1和func2两次,则必须存储结果.例如
stream.map(t -> new AbstractMap.SimpleImmutableEntry<>(func1(t), func2(t))
.filter(e -> e.getKey()!=null && e.getValue()!=null)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Run Code Online (Sandbox Code Playgroud)
这不会使代码更短,甚至效率也取决于具体情况.这种变化不负有心人,如果评估的成本func1和func2高到足以弥补临时对象的创建.原则上,临时对象可以被优化掉,但这不能保证.
从Java 9开始,您可以替换new AbstractMap.SimpleImmutableEntry<>(…)为Map.entry(…).由于此条目类型null从一开始就不允许,因此在构造条目之前需要进行过滤:
stream.flatMap(t -> {
Type1 value1 = func1(t);
Type2 value2 = func2(t);
return value1!=null && value2!=null? Stream.of(Map.entry(value1, value2)): null;
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用您已经使用的库之一的对类型(Java API本身不提供这样的类型).
另一种避免对函数求值两次的方法。使用您选择的配对类。不像Holger那样简洁,但密度稍低一些,更容易阅读。
stream.map(A::doFuncs)
.flatMap(Optional::stream)
.collect(Collectors.toMap(Pair::getKey, Pair::getValue));
private static Optional<Pair<Bar, Baz>> doFuncs(Foo foo)
{
final Bar bar = func1(foo);
final Baz baz = func2(foo);
if (bar == null || baz == null) return Optional.empty();
return Optional.of(new Pair<>(bar, baz));
}
Run Code Online (Sandbox Code Playgroud)
(选择正确的名称 - 我不知道你使用的是什么类型)
| 归档时间: |
|
| 查看次数: |
2305 次 |
| 最近记录: |