java - consultas - comandos cluster linux
¿Cuál es el propósito de la partición? Por (4)
Por ejemplo, si pretendo particionar algunos elementos, podría hacer algo como:
Stream.of("I", "Love", "Stack Overflow")
.collect(Collectors.partitioningBy(s -> s.length() > 3))
.forEach((k, v) -> System.out.println(k + " => " + v));
que produce:
false => [I]
true => [Love, Stack Overflow]
Pero para mí, la partioningBy
es solo un subcaso de groupingBy
. Aunque el primero acepta un Predicate
como parámetro mientras que el último una Function
, simplemente veo una partición como una función de agrupación normal.
Entonces el mismo código hace exactamente lo mismo:
Stream.of("I", "Love", "Stack Overflow")
.collect(Collectors.groupingBy(s -> s.length() > 3))
.forEach((k, v) -> System.out.println(k + " => " + v));
que también resulta en un Map<Boolean, List<String>>
.
Entonces, ¿hay alguna razón por la que deba usar partioningBy
lugar de groupingBy
? Gracias
Otra diferencia entre groupingBy
y partitioningBy
es que la primera toma una Function<? super T, ? extends K>
Function<? super T, ? extends K>
Function<? super T, ? extends K>
y este último un Predicate<? super T>
Predicate<? super T>
.
Cuando pasa una referencia de método o una expresión lambda, como s -> s.length() > 3
, puede usar cualquiera de estos dos métodos (el compilador deducirá el tipo de interfaz funcional según el tipo requerido por el método que elija).
Sin embargo, si tiene una instancia de Predicate<T>
, solo puede pasarla a Collectors.partitioningBy()
. No será aceptado por Collectors.groupingBy()
.
Y de manera similar, si tiene una instancia Function<T,Boolean>
, solo puede pasarla a Collectors.groupingBy()
. No será aceptado por Collectors.partitioningBy()
.
partitioningBy
es un poco más eficiente, utilizando una implementación especial de Map
optimizada para cuando la clave es solo un boolean
.
(También podría ayudar a aclarar lo que quiere decir; partitioningBy
ayuda a comprender de manera eficaz que se está utilizando una condición booleana para particionar los datos).
partitioningBy
siempre devolverá un mapa con dos entradas, una para donde el predicado es verdadero y otra para donde es falso. Es posible que ambas entradas tengan listas vacías, pero existirán.
Eso es algo que groupingBy
no hará, ya que solo crea entradas cuando son necesarias.
En el caso extremo, si envías un flujo vacío a la partitioningBy
ya que aún obtendrás dos entradas en el mapa, mientras que la groupingBy
devolverá un mapa vacío.
EDITAR: Como se menciona a continuación, este comportamiento no se menciona en los documentos de Java, sin embargo, cambiarlo eliminaría el valor agregado que el partitioningBy
está proporcionando actualmente. Para Java 9 esto ya está en las especificaciones.
El método partitioningBy devolverá un mapa cuya clave siempre es un valor booleano, pero en el caso de un método groupingBy , la clave puede ser de cualquier tipo de objeto.
//groupingBy
Map<Object, List<Person>> list2 = new HashMap<Object, List<Person>>();
list2 = list.stream().collect(Collectors.groupingBy(p->p.getAge()==22));
System.out.println("grouping by age -> " + list2);
//partitioningBy
Map<Boolean, List<Person>> list3 = new HashMap<Boolean, List<Person>>();
list3 = list.stream().collect(Collectors.partitioningBy(p->p.getAge()==22));
System.out.println("partitioning by age -> " + list2);
Como puede ver, la clave para el mapa en el caso de partitioningBy method es siempre un valor booleano, pero en el caso de groupingBy method, la clave es Object type
El código detallado es el siguiente:
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String toString() {
return this.name;
}
}
public class CollectorAndCollectPrac {
public static void main(String[] args) {
Person p1 = new Person("Kosa", 21);
Person p2 = new Person("Saosa", 21);
Person p3 = new Person("Tiuosa", 22);
Person p4 = new Person("Komani", 22);
Person p5 = new Person("Kannin", 25);
Person p6 = new Person("Kannin", 25);
Person p7 = new Person("Tiuosa", 22);
ArrayList<Person> list = new ArrayList<>();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.add(p5);
list.add(p6);
list.add(p7);
// groupingBy
Map<Object, List<Person>> list2 = new HashMap<Object, List<Person>>();
list2 = list.stream().collect(Collectors.groupingBy(p -> p.getAge() == 22));
System.out.println("grouping by age -> " + list2);
// partitioningBy
Map<Boolean, List<Person>> list3 = new HashMap<Boolean, List<Person>>();
list3 = list.stream().collect(Collectors.partitioningBy(p -> p.getAge() == 22));
System.out.println("partitioning by age -> " + list2);
}
}