Рубрики
Без рубрики

Раздел списка на Java

Как разделить список с помощью коллекций Guava или Apache Commons.

Автор оригинала: Eugen Paraschiv.

1. Обзор

В этом уроке я проиллюстрирую как разделить список на несколько подсписков заданного размера.

Для относительно простой операции в стандартных API-интерфейсах Java collection на удивление отсутствует поддержка. К счастью, и Guava , и Apache Commons Collections реализовали эту операцию аналогичным образом.

Эта статья является частью серии “Java – Back to Basic” здесь, на Baeldung.

Дальнейшее чтение:

Преобразование списка в строку в Java

Перетасовка Коллекций На Java

Введение в Spliterator на Java

2. Используйте Гуаву для разделения списка

Guava облегчает разбиение списка на подсписки заданного размера – с помощью операции 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. Используйте Гуаву для разделения коллекции

Разделение коллекции также возможно с помощью 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));
}

Имейте в виду, что разделы являются представлениями подсписка исходной коллекции – это означает, что изменения в исходной коллекции будут отражены в разделах:

@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. Используйте коллекции Apache Commons для разделения списка

В последних выпусках коллекций Apache Commons недавно добавлена поддержка секционирования списка:

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

Нет соответствующей опции для разбиения необработанной коллекции – аналогично Guava Iterables.partition в коллекциях Commons.

Наконец, то же самое предостережение применимо и здесь – результирующие разделы являются представлениями исходного списка.

5. Используйте Java 8 для разделения списка

Теперь давайте посмотрим, как использовать Java 8 для разделения нашего списка.

5.1. Секционирование коллекторов

Мы можем использовать Collectors.partitioningBy() для разделения списка на 2 подсписка – следующим образом:

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

Примечание: Результирующие разделы не являются представлением основного списка, поэтому любые изменения, внесенные в основной список, не повлияют на разделы.

5.2. Группировка коллекторов

Мы также можем использовать Collectors.groupingBy() для разделения нашего списка на несколько разделов:

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

Примечание: Так же, как Collectors.partitioningBy() – на результирующие разделы не повлияют изменения в главном списке.

5.3. Разделите список разделителем

Мы также можем использовать Java 8 для разделения нашего списка разделителем:

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

Примечание: Мы использовали “0” в качестве разделителя – сначала мы получили индексы всех элементов “0” в списке, а затем разбили List на эти индексы.

6. Заключение

Представленные здесь решения используют дополнительные библиотеки – Guava или библиотеку Apache Commons Collections. Оба они очень легкие и чрезвычайно полезные в целом, поэтому имеет смысл иметь один из них в пути к классу; однако, если это не вариант – здесь показано решение только для Java .

Реализация всех этих примеров и фрагментов кода может быть найдена на GitHub – это проект на основе Maven, поэтому его должно быть легко импортировать и запускать как есть.