Particionar una lista en Java

1. Información general

En este tutorial, ilustraré cómo dividir una lista en varias sublistas de un tamaño determinado.

Para una operación relativamente simple, sorprendentemente no hay soporte en las API de colección de Java estándar. Afortunadamente, tanto Guava como Apache Commons Collections han implementado la operación de manera similar.

Este artículo es parte de la serie " Java - Back to Basic " aquí en Baeldung.

2. Utilice Guava para dividir la lista

Guava facilita la partición de la Lista en sublistas de un tamaño específico, mediante la operación Lists.partition :

@Test public void givenList_whenParitioningIntoNSublists_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = Lists.partition(intList, 3); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

3. Utilice Guava para particionar una colección

La partición de una colección también es posible con Guava:

@Test public void givenCollection_whenParitioningIntoNSublists_thenCorrect() { Collection intCollection = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Iterable
    
      subSets = Iterables.partition(intCollection, 3); List firstPartition = subSets.iterator().next(); List expectedLastPartition = Lists. newArrayList(1, 2, 3); assertThat(firstPartition, equalTo(expectedLastPartition)); }
    

Tenga en cuenta que las particiones son vistas de sublista de la colección original , lo que significa que los cambios en la colección original se reflejarán en las particiones:

@Test public void givenListPartitioned_whenOriginalListIsModified_thenPartitionsChangeAsWell() { // Given List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = Lists.partition(intList, 3); // When intList.add(9); // Then List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8, 9); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

4. Utilice las colecciones de Apache Commons para dividir la lista

Las últimas versiones de Apache Commons Collections también han agregado recientemente soporte para particionar una Lista:

@Test public void givenList_whenParitioningIntoNSublists_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); List
    
      subSets = ListUtils.partition(intList, 3); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

No hay una opción correspondiente para particionar una colección sin procesar , similar a la partición Guava Iterables.en Commons Collections.

Finalmente, la misma advertencia se aplica aquí también: la partición resultante son vistas de la Lista original.

5. Utilice Java8 para particionar la lista

Ahora, veamos cómo usar Java8 para particionar nuestra Lista.

5.1. Particionamiento de colectores

Podemos usar Collectors.partitioningBy () para dividir la lista en 2 sublistas, de la siguiente manera:

@Test public void givenList_whenParitioningIntoSublistsUsingPartitionBy_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Map
    
      groups = intList.stream().collect(Collectors.partitioningBy(s -> s > 6)); List
     
       subSets = new ArrayList
      
       (groups.values()); List lastPartition = subSets.get(1); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(2)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
      
     
    

Nota: Las particiones resultantes no son una vista de la Lista principal, por lo que cualquier cambio que ocurra en la Lista principal no afectará a las particiones.

5.2. Agrupación de coleccionistas

También podemos usar Collectors.groupingBy () para dividir nuestra lista en múltiples particiones:

@Test public final void givenList_whenParitioningIntoNSublistsUsingGroupingBy_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8); Map
    
      groups = intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3)); List
     
       subSets = new ArrayList
      
       (groups.values()); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
      
     
    

Nota: Al igual que Collectors.partitioningBy () , las particiones resultantes no se verán afectadas por los cambios en la Lista principal.

5.3. Dividir la lista por separador

También podemos usar Java8 para dividir nuestra Lista por separador:

@Test public void givenList_whenSplittingBySeparator_thenCorrect() { List intList = Lists.newArrayList(1, 2, 3, 0, 4, 5, 6, 0, 7, 8); int[] indexes = Stream.of(IntStream.of(-1), IntStream.range(0, intList.size()) .filter(i -> intList.get(i) == 0), IntStream.of(intList.size())) .flatMapToInt(s -> s).toArray(); List
    
      subSets = IntStream.range(0, indexes.length - 1) .mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1])) .collect(Collectors.toList()); List lastPartition = subSets.get(2); List expectedLastPartition = Lists. newArrayList(7, 8); assertThat(subSets.size(), equalTo(3)); assertThat(lastPartition, equalTo(expectedLastPartition)); }
    

Nota: Usamos "0" como separador - primero obtuvimos los índices de todos los elementos "0" en la Lista, luego dividimos la Lista en estos índices.

6. Conclusión

Las soluciones presentadas aquí hacen uso de bibliotecas adicionales: Guava o la biblioteca Apache Commons Collections. Ambos son muy ligeros y extremadamente útiles en general, por lo que tiene mucho sentido tener uno de ellos en la ruta de clases; sin embargo, si esa no es una opción, aquí se muestra una solución exclusiva de Java.

La implementación de todos estos ejemplos y fragmentos de código se puede encontrar en GitHub : este es un proyecto basado en Maven, por lo que debería ser fácil de importar y ejecutar como está.