Java8 Lambda方法

时间:2018-07-06 22:50:04

标签: java lambda java-8

我有这段代码,它根据传入的一组字符串标识符从对象列表中进行过滤,并返回一个字符串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上进行搜索,但找不到任何提示,因此将其发布为问题。

非常感谢您的帮助。 〜灰

4 个答案:

答案 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;
}