【问题标题】:Nested lambda foreach with two different lists (one of the list must be final?)具有两个不同列表的嵌套 lambda foreach(其中一个列表必须是最终的?)
【发布时间】:2020-11-16 10:29:23
【问题描述】:

您能帮我为两个不同的列表编写两个嵌套的 foreach 循环,我需要比较存储在两个列表中的特定对象属性吗?

List<Object1> listOfObject1 = mapper.selectObject1ByName(value1);
List<Object2> listOfObject2 = mapper.selectObject2ByName(value2);

listOfObject1.stream().forEach(object1 -> {
            listOfObject2.stream().forEach(object2 -> {
                if (object1.getCode() == object2.getCode()) {
                    //do something
                }
            });
        });

当然我得到了这个错误:“在 lambda 表达式中使用的变量应该是最终的或有效地最终的”但我不能使任何列表成为最终的,因为上面有一些决策逻辑我用正确的填充列表值,我正在写更多地方的列表。

【问题讨论】:

  • 如果您的“做某事”没有重新分配列表,您可以将列表复制到最终列表
  • 为什么不只使用(增强的)for 循环?
  • 否则,你可以使用普通的 for 循环
  • 我很好奇除了制作另一个列表副本或使用“旧”foreach 循环之外是否还有其他方法。 lambdas 的好处。

标签: java lambda foreach


【解决方案1】:

如果// do something 部分的实现需要object1object2,则可以将适当的代码收集到一个单独的集合中,稍后用于过滤另一个列表中的条目。

例如,如果必须消费object2

class MyClass {
    static void process(List<Object1> listOfObject1, List<Object2> listOfObject2) {

        // set of codes for Object1 instances
        Set<Integer> codes = listOfObject1.stream()
                                          .map(Object1::getCode)
                                          .collect(Collectors.toSet());
        listOfObject2.stream()
                     .filter(o2 -> codes.contains(o2.getCode()))
                     .forEach(MyClass::unarySomething);  // method reference
    }

    static void unarySomething(Object2 o2) {
    }
}

如果object1object2 都以如下方式使用:

static void binarySomething(Object1 o1, Object2 o2) {
}

可以使用groupingBy 创建代码Map&lt;Integer, List&lt;Object1&gt;&gt; mapCodes 的映射,然后应用filterforEach

Map<Integer, List<Object1>> mapCodes = listOfObject1
        .stream()
        .collect(Collectors.groupingBy(Object1::getCode));

listOfObject2.stream()
             .filter(o2 -> mapCodes.containsKey(o2.getCode()))
             .forEach(o2 -> mapCodes.get(o2.getCode())
                                    .forEach(o1 -> binarySomething(o1, o2)));

【讨论】:

    【解决方案2】:

    我们可以简单地使用hashMap来保留list2的所有元素,然后我们可以迭代list1的元素,检查它是否存在于hashMap中。

    final Map<String,Object> mapOfElements= new HashMap<>();
    

    然后您就可以执行所需的操作了。

    list2.forEach(e->mapOfElements.put(e.getCode(),e));

    list1
    .stream()
    .filter(e->mapOfElements.get(e.getCode())
    .collect(Collectors.toList());
    

    【讨论】:

      【解决方案3】:

      我认为您可以定义一个比较函数并使用它来比较列表中的数据。我建议使用 java Comparator 类。这样,用户必须定义​​ compare(T o1, T o2)equals(Object obj) 函数。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-01-09
        • 2012-08-24
        • 2023-01-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多