ion*_*nut 51 java collections java-8 java-stream
我有以下代码:
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;
Run Code Online (Sandbox Code Playgroud)
是否有一种很好的方式有条件地添加元素,可能使用流操作?我想只在列表为空时添加来自method2的元素,否则返回等等.
编辑:值得一提的是,这些方法包含大量逻辑,因此需要防止执行.
Dor*_*ray 67
您可以尝试检查返回值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;
Run Code Online (Sandbox Code Playgroud)
由于延迟评估,addAll添加至少一个元素的第一个操作将阻止其余部分被调用.我喜欢"||"的事实 很好地表达了意图.
ern*_*t_k 45
我只想使用一系列供应商并过滤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;
Run Code Online (Sandbox Code Playgroud)
findFirst()methodN()当其中一个方法返回第一个非空列表时,将阻止不必要的调用.
编辑:
正如下面的评论中所述,如果你的list对象没有用其他任何东西初始化,那么直接返回流的结果是有意义的:
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);
Run Code Online (Sandbox Code Playgroud)
JB *_*zet 17
一种不重复自己的方法就是提取一个为你做的方法:
private void addIfEmpty(List<Object> targetList, Supplier<Collection<?>> supplier) {
if (targetList.isEmpty()) {
targetList.addAll(supplier.get());
}
}
Run Code Online (Sandbox Code Playgroud)
然后
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;
Run Code Online (Sandbox Code Playgroud)
甚至使用for循环:
List<Supplier<Collection<?>>> suppliers = Arrays.asList(this::method1, this::method2, ...);
List<Object> list = new ArrayList<>();
suppliers.forEach(supplier -> this.addIfEmpty(list, supplier));
Run Code Online (Sandbox Code Playgroud)
现在DRY不是最重要的方面.如果您认为原始代码更易于阅读和理解,那么请保持原样.
Ric*_*ola 12
您可以通过创建方法使您的代码更好
public void addAllIfEmpty(List<Object> list, Supplier<List<Object>> method){
if(list.isEmpty()){
list.addAll(method.get());
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它(我假设你的方法不是静态方法,如果你需要使用它们引用它们ClassName::method1)
List<Object> list = new ArrayList<>();
list.addAll(method1());
addAllIfEmpty(list, this::method2);
addAllIfEmpty(list, this::method3);
addAllIfEmpty(list, this::method4);
addAllIfEmpty(list, this::method5);
addAllIfEmpty(list, this::method6);
return list;
Run Code Online (Sandbox Code Playgroud)
如果你真的想使用Stream,你可以这样做
Stream.<Supplier<List<Object>>>of(this::method1, this::method2, this::method3, this::method4, this::method5, this::method6)
.collect(ArrayList::new, this::addAllIfEmpty, ArrayList::addAll);
Run Code Online (Sandbox Code Playgroud)
IMO使它变得更复杂,取决于你的方法被引用的方式,使用循环可能更好
你可以这样创建一个方法:
public static List<Object> lazyVersion(Supplier<List<Object>>... suppliers){
return Arrays.stream(suppliers)
.map(Supplier::get)
.filter(s -> !s.isEmpty()) // or .filter(Predicate.not(List::isEmpty)) as of JDK11
.findFirst()
.orElseGet(Collections::emptyList);
}
Run Code Online (Sandbox Code Playgroud)
然后按如下方式调用它:
lazyVersion(() -> method1(),
() -> method2(),
() -> method3(),
() -> method4(),
() -> method5(),
() -> method6());
Run Code Online (Sandbox Code Playgroud)
方法名称仅用于说明目的.