[英]Java8 lambda approach
我有一段代码,它根据传入的一组字符串标识符从对象列表中进行过滤,并返回字符串 ID 和对象的映射。 类似于以下内容:
class Foo {
String id;
String getId() {return id};
};
// Get map of id --> Foo objects whose string are in fooStr
Map<String,Foo> filterMethod (Set<String> fooStr) {
List<Foo> fDefs; // list of Foo objects
Map<String,Foo> fObjMap = new HashMap<String, Foo>(); // map of String to Foo objects
for (Foo f : fDefs) {
if (fooStr.contains(f.getId()))
fObjMap.put(f.getId(),f);
}
return (fObjMap);
}
有没有更好的 Java8 方法使用过滤器或映射来做到这一点? 我无法弄清楚并尝试在stackoverflow上搜索但找不到任何提示,因此我将其作为问题发布。
任何帮助深表感谢。 ~灰烬
当在最终输出中有条件地包含项目时使用filter
,当从流到地图时使用Collectors.toMap
。 这是你最终的结果:
Map<String,Foo> filterMethod (final Set<String> fooStr) {
List<Foo> fDefs; // list of Foo objects
return fDefs.stream()
.filter(foo -> fooStr.contains(foo.getId()))
.collect(Collectors.toMap(Foo::getId, Function.identity()));
}
虽然ggreiner已经提供了一个有效的解决方案,但当有重复时,你最好处理它,包括一个mergeFunction
。
直接使用Collectors.toMap(keyMapper, valueMapper) ,有一天您会遇到以下问题。
如果映射的键包含重复项(根据 Object.equals(Object)),则在执行集合操作时会抛出IllegalStateException 。 如果映射的键可能有重复项,请改用 toMap(Function, Function, BinaryOperator)。
基于 OP 的解决方案,我认为最好使用
import static java.util.stream.Collectors.*; // save some typing and make it cleaner;
fDefs.stream()
.filter(foo -> fooStr.contains(foo.getId()))
.collect(toMap(Foo::getId, foo -> foo, (oldFoo, newFoo) -> newFoo));
只需使用具有与上述相同谓词的filter
运算符,然后使用toMap
收集器来构建地图。 另请注意,您的迭代解决方案排除了密钥冲突的任何可能性,因此,我也省略了这一点。
Map<String, Foo> idToFooMap = fDefs.stream()
.filter(f -> fooStr.contains(f.getId()))
.collect(Collectors.toMap(Foo::getId, f -> f));
也许是这样的?
Map<String,Foo> filterMethod (Set<String> fooStr) {
List<Foo> fDefs; // get this list from somewhere
Map<String, Foo> fObjMap = new HashMap<> ();
fDefs.stream()
.filter(foo -> fooStr.contains(foo.getId()))
.forEach(foo -> fObjMap.put(foo.getId(), foo))
return fObjMap;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.