【问题标题】:Java8 Stream with Multiple List of Objects具有多个对象列表的 Java8 流
【发布时间】:2019-12-10 11:44:42
【问题描述】:

我有两个列表,我想根据 Object1 和 Object2 的属性执行一些操作。

对象1:

public class Object1 {
        private String prop1;
        private String prop2;
}

对象2:

public class Object2 {
        private String prop1;
        private String prop2;
        private String prop3;
        private boolean prop4;
}

我想使用流而不是使用大方法。

假设我们有以下列表:

List<Object1> object1List = // List of Object1's
List<Object2> object2List = // List of Object2's

现在,我想比较两个列表中的 prop1 和 prop2,如果它们相等,我想从 Object2 中获取 prop3,并且基于 prop3 现在我想从 Object2 中查看 prop4 为 true 的所有元素,并确保所有元素都为 true .

例子:

Object1:
prop1  |  prop2
test1     value1
test1     value2

Object2:
prop1 | prop2 | prop3 | prop4
test1   value1  some    true
test1   value2  some1   true
test2   value3  some    true

现在从上面的例子中,我想流式传输列表并比较列表,如果 prop1 和 prop2 相等,我想在 "some" 的情况下获取 prop3 并获取所有 prop4 值 "true" prop3 的值为“some”并查看 prop1 和 prop2 是否在 Object 的第一个列表中,并将它们收集在一个集合中。我可以用传统方式做到这一点,但流似乎更易读,代码行更少。我只是在学习流,任何想法都值得赞赏!

【问题讨论】:

  • 您是使用 prop1|prop2 字段作为第二个集合中项目的键,还是比较按索引对应的项目?

标签: java collections java-8 stream


【解决方案1】:

由于我无聊到想知道这个问题在问什么,这里有一个使用 Streams 实现此功能的示例。这里的关键是根据适用于流中每个元素的 Predicate 过滤/(any)Match。

Main.java

import java.util.*; import java.util.stream.*;
class Main
{
  public static void main(String[] args) 
  {
    List<Object1> l1 = new ArrayList<>();//referred to as "first list" in comments
    List<Object2> l2 = new ArrayList<>();//referred to as "second list" in comments
    l1.add(new Object1("test1","value1"));
    l1.add(new Object1("test1","value2"));
    l2.add(new Object2("test1", "value1", "some", true));
    l2.add(new Object2("test1", "value2", "some1", true));
    l2.add(new Object2("test2", "value3", "some", true));
    //This is the stream of objects2 in second list that matched both prop1 and prop2 for at least one object1 in first list
    Stream<Object2> matchingProp1andProp2 = l2.stream().filter(obj2 -> l1.stream().anyMatch(obj1 -> obj1.prop1().equals(obj2.prop1()) && obj1.prop2().equals(obj2.prop2())));
    matchingProp1andProp2.forEach(match -> {
      //get the ones in second list that have same prop3 as the match and prop4 being true
      Stream<Object2> matchingCriteria = l2.stream().filter(obj2 -> match.prop3().equals(obj2.prop3()) && obj2.prop4());
      System.out.println(matchingCriteria.collect(Collectors.toList()));
    });
  }
}

【讨论】:

    【解决方案2】:

    选项1 - 如果您认为单独阅读每个条件更容易:

    Set<Object2> result = l2.stream().filter(o -> o.getProp3().equals("some"))
                                     .filter(o -> l1.contains(new Object1(o.getProp1(), o.getProp2())))
                                     .filter(Object2::isProp4)
                                     .collect(Collectors.toSet());
    

    选项2 - 一个过滤器满足所有条件:

    result = l2.stream().filter(o -> o.getProp3().equals("some") && l1.contains(new Object1(o.getProp1(), o.getProp2())) && o.isProp4() ).collect(Collectors.toSet());
    

    我假设您的 Object1 覆盖了 equals 和 hasCode,因此您可以使用 contains。

    如果不是这样,那就有点复杂了,因为你必须分别比较 prop1 和 prop2,而不是对象本身:

    result = l2.stream().filter(o -> o.getProp3().equals("some") && o.isProp4())
                        .filter(o1 -> l1.stream().anyMatch(o2 -> o2.getProp1().equals(o1.getProp1()) && o2.getProp2().equals(o1.getProp2())))
                        .collect(Collectors.toSet());
    

    【讨论】:

      猜你喜欢
      • 2023-03-14
      • 1970-01-01
      • 1970-01-01
      • 2014-05-04
      • 2019-02-01
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多