Java 8:根据集合中的属性获取对象的更好方法是什么

时间:2016-07-08 00:50:35

标签: lambda java-8 java-stream

考虑以下课程:

@Setter
@Getter
@EqualsAndHashCode(exclude = "text")
@ToString
public class Foo {
    private Long xKey;
    private Long yKey;
    private String text
}

如果我有List<Foo> fooList,我必须在其中获取列表元素:

{xKey, yKey} combination is in Map<Long,Long> combination = {{10L,20L},{11L,35L},{4L,1L}}

每次迭代都使用.get()方法:

for(Entry<Long,Long> entry: combination.entrySet()){
    Foo tempFoo = new Foo(entry.getKey(),entry.getValue(),null);
    Foo actualFoo = fooList.get(tempFoo);
    System.out.println(actualFoo);
}

第二种方式是java 8流

combination.foreach((k,v) -> {
    Foo actualFoo = fooList.stream()
           .filter(f -> f.getXKey.equals(k) && f.getYKey.equals(v))
           .findFirst()
           .orElse(null);
    System.out.println(actualFoo);
})

哪一个在性能和编码实践方面更好?

编辑:在查看评论后发现第一个代码段而不是fooList.get(tempFoo);出现了错误,应该是fooList.get(fooList.indexOf(tempFoo));

4 个答案:

答案 0 :(得分:3)

你可以缩短它:

fooList.stream()
  .filter(f -> Objects.equals(f.getYKey(), combination.get(f.getXKey())))
  .forEach(System.out::println);

答案 1 :(得分:2)

首先,List<Foo>显然没有get(Foo),这只是list.get(list.indexOf(foo))之类的描述,以获取模板的实际实例,这意味着与您的Stream变体一样的线性搜索。

在这方面,两者不鼓励,因为它们意味着对Map进行线性迭代,在列表上执行另一个嵌套线性搜索,而Map通常具有查找操作比线性搜索更好。

因此,您应该遍历列表并在Map上执行查找:

for(Foo foo: fooList) {
    if(foo.getYKey().equals(combination.get(foo.getXKey()))) {
        System.out.println(foo);
    }
}

唯一的区别是元素没有以Map的顺序出现,以防地图 定义的顺序(HashMap没有)并且它不会为列表中没有相应null的映射打印Foo

当然,您也可以将其写为forEach操作:

fooList.forEach(foo -> {
    if(foo.getYKey().equals(combination.get(foo.getXKey()))) {
        System.out.println(foo);
    }
});

或流操作

fooList.stream()
       .filter(foo -> foo.getYKey().equals(combination.get(foo.getXKey())))
       .forEach(System.out::println);

都是等价的。

所做的事情,是使用Stream搜索操作替换Map.get之类的内部Collection API查找操作。

答案 2 :(得分:1)

您将列表视为一个集合,因此我建议相应地更改实现。将它作为一个集合,您将获得更好的性能,例如使用HashSet作为实现。在这种情况下,我还强烈建议不要尝试流式传输新的set实现,因为简单的查找将比索引更快地工作。

答案 3 :(得分:0)

第二种解决方案更具可读性。第一个将无法工作,因为get in list的预期参数是一个int,它是列表的索引。对于循环和聚合操作具有基本相同的复杂性,因此没有真正的性能差异,除非第一个解决方案稍微差一些,因为它正在创建那些临时的Foo对象。