1. 개요

이 기사에서는 List를 주어진 크기의 여러 하위 List으로 분할하는 방법을 설명합니다 .

상대적으로 간단한 작업의 경우 놀랍게도 표준 Java 컬렉션 API에서 지원하지 않습니다. 운 좋게도 GuavaApache Commons Collections 모두 유사한 방식으로 작업을 구현했습니다.

이 기사는 여기 Baeldung에서 " Java – Back to Basic " 시리즈 의 일부입니다 .

2. 구아바를 사용하여 List 분할

Guava는 Lists.partition 작업을 통해 List를 지정된 크기의 하위 List으로 분할하는 것을 용이하게 합니다 .

@Test
public void givenList_whenParitioningIntoNSublists_thenCorrect() {
    List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
    List<List<Integer>> subSets = Lists.partition(intList, 3);

    List<Integer> lastPartition = subSets.get(2);
    List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);
    assertThat(subSets.size(), equalTo(3));
    assertThat(lastPartition, equalTo(expectedLastPartition));
}

3. Guava를 사용하여 컬렉션 분할

Guava를 사용하여 컬렉션을 분할 할 수도 있습니다.

@Test
public void givenCollection_whenParitioningIntoNSublists_thenCorrect() {
    Collection<Integer> intCollection = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

    Iterable<List<Integer>> subSets = Iterables.partition(intCollection, 3);

    List<Integer> firstPartition = subSets.iterator().next();
    List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(1, 2, 3);
    assertThat(firstPartition, equalTo(expectedLastPartition));
}

파티션은 원본 컬렉션의 하위 List 보기 이므로 원본 컬렉션의 변경 사항이 파티션에 반영됩니다.

@Test
public void givenListPartitioned_whenOriginalListIsModified_thenPartitionsChangeAsWell() {
    // Given
    List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
    List<List<Integer>> subSets = Lists.partition(intList, 3);

    // When
    intList.add(9);

    // Then
    List<Integer> lastPartition = subSets.get(2);
    List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8, 9);
    assertThat(lastPartition, equalTo(expectedLastPartition));
}

4. Apache Commons Collections를 사용하여 List 분할

Apache Commons Collections의 최신 릴리스에는 최근 List 분할에 대한 지원이 추가되었습니다.

@Test
public void givenList_whenParitioningIntoNSublists_thenCorrect() {
    List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);
    List<List<Integer>> subSets = ListUtils.partition(intList, 3);

    List<Integer> lastPartition = subSets.get(2);
    List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);
    assertThat(subSets.size(), equalTo(3));
    assertThat(lastPartition, equalTo(expectedLastPartition));
}

Commons Collections 에는 Guava Iterables.partition과 유사한 원시 컬렉션을 분할하는 해당 옵션이 없습니다 .

마지막으로 동일한 경고가 여기에도 적용됩니다. 결과 파티션은 원래 List의 뷰입니다.

5. Java8을 사용하여 List 분할

이제 Java8을 사용하여 List을 분할하는 방법을 살펴보겠습니다.

5.1. 수집기 파티셔닝 기준

Collectors.partitioningBy()를 사용하여 List을 2개의 하위 List으로 나눌 수 있습니다 .

@Test
public void givenList_whenParitioningIntoSublistsUsingPartitionBy_thenCorrect() {
    List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

    Map<Boolean, List<Integer>> groups = 
      intList.stream().collect(Collectors.partitioningBy(s -> s > 6));
    List<List<Integer>> subSets = new ArrayList<List<Integer>>(groups.values());

    List<Integer> lastPartition = subSets.get(1);
    List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);
    assertThat(subSets.size(), equalTo(2));
    assertThat(lastPartition, equalTo(expectedLastPartition));
}

참고: 결과 파티션은 기본 List 보기가 아니므로 기본 List에 발생하는 모든 변경 사항은 파티션에 영향을 주지 않습니다.

5.2. 수집기 그룹화 기준

또한 Collectors.groupingBy()를 사용하여 List을 여러 파티션으로 나눌 수 있습니다 .

@Test
public final void givenList_whenParitioningIntoNSublistsUsingGroupingBy_thenCorrect() {
    List<Integer> intList = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8);

    Map<Integer, List<Integer>> groups = 
      intList.stream().collect(Collectors.groupingBy(s -> (s - 1) / 3));
    List<List<Integer>> subSets = new ArrayList<List<Integer>>(groups.values());

    List<Integer> lastPartition = subSets.get(2);
    List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);
    assertThat(subSets.size(), equalTo(3));
    assertThat(lastPartition, equalTo(expectedLastPartition));
}

참고: Collectors.partitioningBy() 와 마찬가지로 결과 파티션은 기본 List의 변경 사항에 영향을 받지 않습니다.

5.3. 구분 기호로 List 분할

Java8을 사용하여 List을 구분 기호로 나눌 수도 있습니다.

@Test
public void givenList_whenSplittingBySeparator_thenCorrect() {
    List<Integer> 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<List<Integer>> subSets = 
      IntStream.range(0, indexes.length - 1)
               .mapToObj(i -> intList.subList(indexes[i] + 1, indexes[i + 1]))
               .collect(Collectors.toList());

    List<Integer> lastPartition = subSets.get(2);
    List<Integer> expectedLastPartition = Lists.<Integer> newArrayList(7, 8);
    assertThat(subSets.size(), equalTo(3));
    assertThat(lastPartition, equalTo(expectedLastPartition));
}

참고: "0"을 구분 기호로 사용했습니다. 먼저 List의 모든 "0" 요소 인덱스를 얻은 다음 이 인덱스에서 List를 분할합니다.

6. 결론

여기에 제시된 솔루션은 추가 라이브러리, 즉 Guava 및 Apache Commons Collections를 사용합니다. 둘 다 매우 가볍고 전반적으로 매우 유용하므로 클래스 경로에 둘 중 하나를 두는 것이 완벽합니다. 그러나 이것이 옵션이 아닌 경우 Java 전용 솔루션이 여기에 표시됩니다 .

이러한 모든 예제와 코드 스니펫의 구현은 GitHub에서 찾을 수 있습니다 . 이것은 Maven 기반 프로젝트이므로 그대로 가져오고 실행하기 쉬워야 합니다.

res – REST with Spring (eBook) (everywhere)