当前位置: 首页 > 知识库问答 >
问题:

Java 8 列表处理 - 有条件地添加元素

常翰
2023-03-14

我有以下一段代码:

List<Object> list = new ArrayList<>();
list.addAll(method1());
if(list.isEmpty()) { list.addAll(method2()); }
if(list.isEmpty()) { list.addAll(method3()); }
if(list.isEmpty()) { list.addAll(method4()); }
if(list.isEmpty()) { list.addAll(method5()); }
if(list.isEmpty()) { list.addAll(method6()); }
return list;

有没有一种很好的方法可以有条件地添加元素,比如使用流操作?我只想在列表为空时添加method2中的元素,否则返回,以此类推。

编辑:值得一提的是,这些方法包含繁重的逻辑,因此需要防止执行。

共有3个答案

江渊
2023-03-14

一种不重复自己的方法是提取一种为你做的方法:

private void addIfEmpty(List<Object> targetList, Supplier<Collection<?>> supplier) {
    if (targetList.isEmpty()) {
        targetList.addAll(supplier.get());
    }
}

然后

List<Object> list = new ArrayList<>();
addIfEmpty(list, this::method1);
addIfEmpty(list, this::method2);
addIfEmpty(list, this::method3);
addIfEmpty(list, this::method4);
addIfEmpty(list, this::method5);
addIfEmpty(list, this::method6);
return list;

或者甚至使用for循环

List<Supplier<Collection<?>>> suppliers = Arrays.asList(this::method1, this::method2, ...);
List<Object> list = new ArrayList<>();
suppliers.forEach(supplier -> this.addIfEmpty(list, supplier));

现在干燥不是最重要的方面。如果您认为您的原始代码更易于阅读和理解,请保持这样。

陈实
2023-03-14

我会简单地使用供应商流并过滤List.isEmpty

Stream.<Supplier<List<Object>>>of(() -> method1(), 
                                  () -> method2(), 
                                  () -> method3(), 
                                  () -> method4(), 
                                  () -> method5(), 
                                  () -> method6())
    .map(Supplier<List<Object>>::get)
    .filter(l -> !l.isEmpty())
    .findFirst()
    .ifPresent(list::addAll);

return list;

findFirst()将防止在其中一个方法返回第一个非空列表时对方法N()的不必要调用。

编辑:
如下面的评论中所述,如果您的列表对象未使用其他任何内容初始化,则直接返回流的结果是有意义的:

return  Stream.<Supplier<List<Object>>>of(() -> method1(), 
                                          () -> method2(), 
                                          () -> method3(), 
                                          () -> method4(), 
                                          () -> method5(), 
                                          () -> method6())
    .map(Supplier<List<Object>>::get)
    .filter(l -> !l.isEmpty())
    .findFirst()
    .orElseGet(ArrayList::new);
谷梁星雨
2023-03-14

您可以尝试检查 addAll 的返回值。每当列表被修改时,它将返回 true,因此请尝试以下操作:

List<Object> list = new ArrayList<>();
// ret unused, otherwise it doesn't compile
boolean ret = list.addAll(method1())
    || list.addAll(method2()) 
    || list.addAll(method3())
    || list.addAll(method4())
    || list.addAll(method5())
    || list.addAll(method6());
return list;

由于惰性求值,第一个添加至少一个元素的 addAll 操作将阻止其余元素被调用。我喜欢“||”很好地表达了意图。

 类似资料:
  • 正如这篇stackoverflow文章中所述,在调用终端操作之前,不会实际应用筛选器。既然我在调用终端操作之前重新分配了stream的值,那么上面的代码是否仍然是使用Java8流的适当方法呢?

  • 问题内容: 是否可以根据条件向标签添加内容?像在此示例中一样,当我只想在第一次迭代中添加时(仅用于的第一个元素)? 问题答案: 是的,在这种情况下,AngularJS具有两个指令: 可以使用ng-show / ng-hide指令族基于评估表达式的结果来隐藏(通过使用显示CSS规则)DOM 3的一部分。 如果我们想有条件地物理删除/添加DOM的一部分,那么ng-switch指令家族(ng-switc

  • 本文向大家介绍aurelia 有条件地添加或删除HTML元素,包括了aurelia 有条件地添加或删除HTML元素的使用技巧和注意事项,需要的朋友参考一下 示例 与show.bind使用时不同,if.bind如果提供的绑定值是,则元素将从页面中删除;如果值为,则将元素false添加到页面中true。 分组元素 有时可能需要一次性添加或删除整组元素。为此,我们可以使用<template>元素来显示或

  • 问题内容: Collector的Javadoc显示了如何将流的元素收集到新的List中。有没有一种将结果添加到现有ArrayList中的方法? 问题答案: 注意: osid的答案 显示了如何使用来添加到现有集合。这是对现有集合进行变异的有用且有效的技术。我的答案解决了为什么您不应该使用A 来突变现有集合的原因。 简短的答案是 no ,至少在一般情况下不是这样,您不应该使用a 来修改现有集合。 原因

  • Collector的Javadoc展示了如何将流的元素收集到一个新列表中。是否有一个单行程序将结果添加到现有的ArrayList中?

  • 我有问题动态添加jsx表行到表中的反应。 我的案例如下: 如果表行包含子行,请将它们添加到主行之外。 这是我最初的设计: 问题是不允许div作为tbody标记中的子级。你知道我怎样才能不把我的报税单写进div里就解决这个问题吗? 我在考虑将整个tbody移动到我的行组件,并有条件地在那里渲染子行,但是我看不出这有什么帮助,因为我仍然不能在返回周围使用任何包装器...我唯一能使用的包装器是tbody