我有这段代码,它根据传入的一组字符串标识符从对象列表中进行过滤,并返回一个字符串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上进行搜索,但找不到任何提示,因此将其发布为问题。
非常感谢您的帮助。 〜灰
答案 0 :(得分:2)
在最终输出中有条件地包含项目时,请使用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()));
}
答案 1 :(得分:2)
尽管 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));
答案 2 :(得分:1)
这是一种基于Java 8的纯方法,
Map<String, Foo> filteredFoos = fDefs.stream()
.filter(f -> fooStr.stream().anyMatch(fs -> Objects.equals(f, fs)))
.collect(Collectors.toMap(Foo::getId, Function.identity()));
这种方法更加并行友好。但是,由于您使用的是基于hash
的集合,contains(someValue)
的性能可能会更好。基于散列的集合上的contains
将以O(1)
的运行时复杂度运行,而不是采用基于O(n)
的方法的anyMatch
运行时复杂度。
答案 3 :(得分:0)
也许是这样吗?
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;
}