Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

152
Vistas
¿Cómo descuidar los objetos durante la agrupación o partición de secuencias?

¿Es posible ignorar algunos elementos durante Collectors.groupingBy o Collectors.partitioningBy ?

Por supuesto, sé que puedo colocar un .filter() en cualquier lugar de una secuencia. Pero mi problema es que tengo que ejecutar una evaluación bastante compleja y costosa para decidir en qué "grupo" se deben dividir mis objetos.

Además, siempre hay muchos objetos que me gustaría descuidar durante la recolección.

Ejemplo: imagina una List<Foo> , que quiero dividir en 2 listas. Eso es fácil, pero ¿cómo puedo ignorar adicionalmente todos los objetos que no encajan en mi condición evaluada?

 var map = foos.stream().collect(Collectors.groupingBy( foo -> { int bar = complexEvaluation(foo); if (bar > 1000) return true; if (bar < 0) return false; //TODO how to neglect the rest between 0-1000 }, Collectors.mapping(foo -> foo.id, Collectors.toSet()) ));
over 4 years ago · Santiago Trujillo
4 Respuestas
Responde la pregunta

0

Para reutilizar el resultado de complexE Evaluation tanto en filter como en groupingBy , puede llamar antes de filtrar y almacenar el resultado en una clase contenedora.

 foos.stream() .map(foo -> { int bar = complexEvaluation(foo); if (bar > 1000) Pair.of(foo, true); if (bar < 0) Pair.of(foo, false); return Pair.of(foo, null); ) .filter(fooPair -> fooPair.getRight() != null) .collect(Collectors.groupingBy( Pair::getRight(), Collectors.mapping(fooPair -> fooPair.getLeft().id, Collectors.toSet() );

Sin embargo, esto es solo si insiste en usar groupingBy por alguna razón.

Una alternativa con foreach sería mucho más fácil de leer:

 Map<Boolean, Set<Foo>> groups = new HashMap<>(); foos.stream() .forEach(foo -> { int bar = complexEvaluation(foo); if (bar > 1000) groups.computeIfAbsent(true, k->new HashSet<>()).add(foo); if (bar < 0) groups.computeIfAbsent(false, k->new HashSet<>()).add(foo); })
over 4 years ago · Santiago Trujillo Denunciar

0

Si entiendo su intención correctamente, desea filtrar algunos valores mientras los recopila. Es factible con Collectors.filtering() .

Tenga en cuenta que el filtering() puede eliminar todos los valores de algunos depósitos, pero no hará que se eliminen los depósitos vacíos. En el siguiente ejemplo, los cubos para 1, 2, 3, 4, 5 estarán vacíos.

 public static void main(String[] args) { var foos = List.of(-100, 1, 2, 3, 4, 5, 1001, 1002, 1003); var map = foos.stream() .collect(Collectors.groupingBy( UnaryOperator.identity(), Collectors.filtering(foo -> foo < 0 || foo > 1000, Collectors.toSet()))); System.out.println(map); }

mapa

 {1=[], 2=[], 3=[], -100=[-100], 4=[], 5=[], 1001=[1001], 1002=[1002], 1003=[1003]}

ACTUALIZAR

Revisé este problema y la solución proporcionada a continuación calcula los valores de antemano.

En esta versión, las entradas no deseadas se filtran en la secuencia, lo que hace que el código dentro de Collector sea más fácil de leer. Espero que en lugar de foo objects se use un número entero no sea un problema.

 public static void main(String[] args) { List<Integer> foos = List.of(-100, 1, 2, 3, 4, 5, 101, 102, 103); Map<Integer, Integer> fooToValue = getFooToValueMap(foos); Map<Boolean, Set<Integer>> map = getFoosMap(fooToValue); System.out.println(map); }
 private static Map<Boolean, Set<Integer>> getFoosMap(Map<Integer, Integer> fooToValue) { return fooToValue.entrySet().stream() .filter(entry -> entry.getValue() < 0 || entry.getValue() > 1000) .collect(Collectors.partitioningBy( entry -> entry.getValue() > 1000, Collectors.mapping(Map.Entry::getKey, Collectors.toSet()) )); }
 private static Map<Integer, Integer> getFooToValueMap(List<Integer> list) { return list.stream() .collect(Collectors.toMap(UnaryOperator.identity(), foo -> complexEvaluation(foo))); }
 private static int complexEvaluation(int foo) { return (int) Math.signum(foo) * foo * foo; }

mapa

 {false=[-100], true=[101, 102, 103]}
over 4 years ago · Santiago Trujillo Denunciar

0

Simplemente use una enum para definir sus 3 casos:

 enum Categories { HIGH, LOW, NEGATIVE } var map = foos.stream().collect(Collectors.groupingBy( foo -> { int bar = complexEvaluation(foo); if (bar > 1000) return HIGH; if (bar < 0) return NEGATIVE; return LOW; }, Collectors.mapping(foo -> foo.id, Collectors.toSet()) ));

Luego ignore o elimine LOW si no lo necesita. También tiene los beneficios adicionales de dar más significado a sus categorías en lugar de simplemente nombrarlas true / false , y facilita la refactorización si necesita más categorías en el futuro.

El único inconveniente es que crea un conjunto LOW inútil, pero eso solo es un problema si es realmente grande en comparación con los otros conjuntos y la operación complexEvaluation() .

over 4 years ago · Santiago Trujillo Denunciar

0

Si desea evitar el almacenamiento temporal, debe implementar su propio recopilador:

 var map = foos.parallelStream().collect( () -> Map.of(true, new HashSet<ID>(), false, new HashSet<ID>()), (o, foo) -> { int bar = complexEvaluation(foo); ID id = foo.id; if (bar > 1000) o.get(true).add(id); else if (bar < 0) o.get(false).add(id); }, (a, b) -> { a.get(true).addAll(b.get(true)); a.get(false).addAll(b.get(false)); } );

Este ejemplo tiene el mismo comportamiento que partitioningBy , siempre creando entradas para true y false .

ID es un marcador de posición para el tipo de foo.id que no incluyó en la pregunta.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda