エキサイト株式会社エンジニア佐々木です。JavaでList分割する方法をJava標準のみで実装するTipsです。
環境
$ java --version openjdk 17.0.1 2021-10-19 OpenJDK Runtime Environment (build 17.0.1+12-39) OpenJDK 64-Bit Server VM (build 17.0.1+12-39, mixed mode, sharing)
数字のリスト分割する
下記のリストを5件ずつ分割する
List<Integer> originalList = IntStream.rangeClosed(1, 20).boxed().toList(); // originalListの中身 // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
List
これは中にあるデータでグルーピングをすると分割できます。
int partitionSize = 5; Collection<List<Integer>>list = originalList .stream() .collect(Collectors.groupingBy(e -> (e - 1) / partitionSize)) .values(); log.info("{}", collect); // listの中身 // [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]]
文字列のリストを分割する
下記のa-z
までの文字列をリストを5つずつ分割してみます。
下記のリストを用意します。
List<String> originalList = IntStream.rangeClosed('a', 'z').mapToObj(e -> String.valueOf((char)e)).toList(); // originalListの中身 // [a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z]
List.subListを使う方法
List.subListを使う方法は下記になります。
int partitionSize = 5; List<List<Integer>> list = IntStream .range(0, (originalList.size()-1) / partitionSize) // いくつリストを作るかを設定 .mapToObj(e -> originalList.subList( e * partitionSize, Math.min((e + 1) * partitionSize, originalList.size()) // fromIndexとtoIndexを計算してセットする ) ).toList(); // listの中身 // [[a, b, c, d, e], [f, g, h, i, j], [k, l, m, n, o], [p, q, r, s, t], [u, v, w, x, y], [z]]
subListの場合は、fromIndexとtoIndexの作る必要があるので、その計算を行わないといけません。下記の部分になります。
e * partitionSize, Math.min((e + 1) * partitionSize, originalList.size())
Collectors.groupingByを使う方法
Collectors.groupingByを使うと、先程の計算処理が不要になります。
こちらだと、index / partitionSize
の値でグルーピングしつつ、Collectors.mapping(index -> originalList.get(index), Collectors.toList()
でoriginalListから値を取り出し、Listに設定するということをやっています。
Collection<List<String>> list = IntStream .range(0, originalList.size()) .boxed() .collect( Collectors.groupingBy( index -> index / partitionSize, // `index / partitionSize`の値でMapのKeyを作成する Collectors.mapping(index -> originalList.get(index), Collectors.toList() // MapのValueをoriginalListから取り出し、リスト生成をしてセットする ) ) ).values(); // 最後にコレクションに変換する // listの中身 // [[a, b, c, d, e], [f, g, h, i, j], [k, l, m, n, o], [p, q, r, s, t], [u, v, w, x, y], [z]]
JavaのLambda式とグルーピングの処理は初見では分かりづらいかもですが、わかってしまうとかなり使いこなせそうです。
まとめ
GuavaやApacheCommonsCollectionなどのライブラリでもっと簡単にList分割をすることはできますが、このためだけに依存ライブラリを増やしたくはありません。ぜひ使ってみてください。
最後に
エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しております。長期インターンも歓迎していますので、興味があれば連絡いただければと思います。
カジュアル面談はこちらになります! meety.net
募集職種一覧はこちらになります!(カジュアルからもOK) www.wantedly.com