LoginSignup
9
9

Listを任意の要素数ごとに分割する

Last updated at Posted at 2017-05-18

概要

  • 与えられたListを任意の数の要素ごとに複数のListに分割する
    • OracleのIN句のように一度に処理できる要素数に上限がある場合に有効

Java 8の場合

Java 8ではストリームAPIを活用しリストを分割する

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class CollectionUtils {
    public static <T> List<List<T>> chunk(List<T> list, int size) {
        if (list == null || list.isEmpty() || size <= 0) {
            return Collections.emptyList();
        }

        int block = list.size() / size + (list.size() % size > 0 ? 1 : 0);

        return IntStream.range(0, block)
            .boxed()
            .map(i -> {
                int start = i * size;
                int end = Math.min(start + size, list.size());
                return list.subList(start, end);
            })
            .collect(Collectors.toList());
    }
}

さらにコンパクトな例 (@natty420 さんより)

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class CollectionUtils {
    public static <T> List<List<T>> chunk(List<T> list, int size) {
        return IntStream.range(0, (int) Math.ceil((double) list.size() / (double) size))
            .boxed()
            .map(i -> list.stream().skip((long) i * size).limit(size).collect(Collectors.toList()))
            .collect(Collectors.toList());
    }
}

Java 9以降の場合

Java 9の導入されたStream.iterateを利用できる

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class CollectionUtils {
    public static <T> List<List<T>> chunk(List<T> list, int size) {
        return Stream.iterate(0, n -> n + size)
            .limit((list.size() + size - 1) / size)
            .map(n -> list.subList(n, Math.min(n + size, list.size())))
            .collect(Collectors.toList());
    }
}

Google Guavaライブラリの使用

Lists.partitionが同等の機能を提供している

import com.google.common.collect.Lists;

import java.util.List;

public class CollectionUtils {
    public static <T> List<List<T>> chunk(List<T> list, int size) {
        return Lists.partition(list, size);
    }
}

テストケース

JUnit
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.util.Arrays;

public class CollectionUtilsTest {
    @Test
    void testChunk() {
        Assertions.assertEquals(
            // Expected
            Arrays.asList(
                Arrays.asList(1, 2, 3),
                Arrays.asList(4, 5, 6),
                Arrays.asList(7, 8, 9),
                Arrays.asList(10)
            ),
            // Actual
            CollectionUtils.chunk(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 3)
        );
    }

}

参考

9
9
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9