uso una salir recorrer obtener listas lista interfaz grafica eliminar elementos datos como boton borrar agregar java collections java-8 java-stream

una - lista jframe java



Procesamiento de listas de Java 8-agregar elementos condicionalmente (5)

Tengo el siguiente código:

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;

¿Hay una buena manera de agregar elementos condicionalmente, tal vez utilizando operaciones de transmisión? Me gustaría agregar elementos del método 2 solo si la lista está vacía, de lo contrario, vuelva, y así sucesivamente.

Edición: vale la pena mencionar que los métodos contienen una lógica pesada, por lo que debe evitarse su ejecución.


Podría intentar verificar el valor de retorno de addAll . Devolverá true cuando la lista haya sido modificada, así que intente esto:

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;

Debido a la evaluación perezosa, la primera operación addAll que agregó al menos un elemento evitará que se llame al resto. Me gusta el hecho de que "||" Expresa la intención bastante bien.


Podrías crear un método como tal:

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); }

y luego llámalo como sigue:

lazyVersion(() -> method1(), () -> method2(), () -> method3(), () -> method4(), () -> method5(), () -> method6());

Nombre del método con fines ilustrativos únicamente.


Podrías mejorar tu código creando el método.

public void addAllIfEmpty(List<Object> list, Supplier<List<Object>> method){ if(list.isEmpty()){ list.addAll(method.get()); } }

Luego puede usarlo así (asumí que sus métodos no son métodos estáticos, si es que necesitan hacer referencia a ellos usando 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;

Si realmente quieres usar un Stream, puedes hacer esto

Stream.<Supplier<List<Object>>>of(this::method1, this::method2, this::method3, this::method4, this::method5, this::method6) .collect(ArrayList::new, this::addAllIfEmpty, ArrayList::addAll);

OMI lo hace más complicado, dependiendo de cómo se hace referencia a sus métodos, podría ser mejor usar un bucle


Simplemente usaría un flujo de proveedores y filtraría en 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() evitará llamadas innecesarias al methodN() cuando uno de los métodos methodN() la primera lista que no esté vacía.

EDITAR:
Como se comentó en los comentarios a continuación, si su objeto de list no se inicializa con nada más, entonces tiene sentido simplemente devolver el resultado de la secuencia directamente:

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);


Una forma de hacerlo sin repetirte es extraer un método que lo haga por ti:

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

Y entonces

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;

O incluso usar un bucle for:

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

Ahora DRY no es el aspecto más importante. Si cree que su código original es más fácil de leer y entender, entonces manténgalo así.