Java 逆引き集 | distinct / limit / skip — 重複排除・ページング処理

Java Java
スポンサーリンク

distinct / limit / skip — 重複排除・ページング処理

Stream API の中間操作でよく使うのが distinct(重複排除)limit(先頭から指定件数だけ残す)skip(先頭から指定件数を飛ばす)。これらを組み合わせると「ユニーク化」「ページング」「部分抽出」が簡単に書けます。


基本の役割

  • distinct:
    • 要素の重複を排除(equals/hashCode に基づく)。
    • 全体を見て処理するため、大量データではメモリ負荷に注意。
  • limit(n):
    • 先頭から n 件だけ残す。
    • ページングや「サンプル抽出」に便利。
  • skip(n):
    • 先頭から n 件を飛ばす。
    • ページングの「開始位置」を指定するのに使う。

基本コード例

distinct(重複排除)

List<String> names = List.of("A","B","A","C","B");
List<String> uniq = names.stream()
                         .distinct()
                         .toList();
System.out.println(uniq); // [A, B, C]
Java

limit(先頭から指定件数)

List<Integer> nums = List.of(1,2,3,4,5);
List<Integer> first3 = nums.stream()
                           .limit(3)
                           .toList();
System.out.println(first3); // [1, 2, 3]
Java

skip(先頭を飛ばす)

List<Integer> nums = List.of(1,2,3,4,5);
List<Integer> after2 = nums.stream()
                           .skip(2)
                           .toList();
System.out.println(after2); // [3, 4, 5]
Java

例題で理解する

例題1: ユーザーリストから「重複を除いた先頭10件」

List<String> users = List.of("u1","u2","u1","u3","u4","u2","u5","u6","u7","u8","u9","u10","u11");

List<String> page = users.stream()
                         .distinct()   // 重複排除
                         .limit(10)    // 先頭10件
                         .toList();

System.out.println(page); // [u1, u2, u3, u4, u5, u6, u7, u8, u9, u10]
Java

例題2: ページング処理(2ページ目を取得)

List<Integer> data = IntStream.rangeClosed(1, 50).boxed().toList();
int pageSize = 10;
int pageNum = 2; // 0始まり → 2ページ目は skip(20)

List<Integer> page = data.stream()
                         .skip(pageNum * pageSize)
                         .limit(pageSize)
                         .toList();

System.out.println(page); // [21,22,23,24,25,26,27,28,29,30]
Java
  • ポイント: skip で開始位置を飛ばし、limit で件数を制御。

例題3: ログから「重複行を除き、最新20件だけ」

List<String> logs = List.of("WARN a","ERROR b","WARN a","INFO c","ERROR b","DEBUG d");

List<String> latest = logs.stream()
                          .distinct()
                          .skip(Math.max(0, logs.size() - 20)) // 最新20件に絞る
                          .toList();

System.out.println(latest); // [WARN a, ERROR b, INFO c, DEBUG d]
Java

テンプレート集

  • 重複排除
stream.distinct().toList();
Java
  • 先頭N件だけ
stream.limit(N).toList();
Java
  • 先頭M件を飛ばす
stream.skip(M).toList();
Java
  • ページング(pageNum, pageSize)
stream.skip(pageNum * pageSize)
      .limit(pageSize)
      .toList();
Java
  • 重複排除+ページング
stream.distinct()
      .skip(pageNum * pageSize)
      .limit(pageSize)
      .toList();
Java

落とし穴と回避策

  • distinct は equals/hashCode に依存:
    • 独自クラスでは equals/hashCode を正しく実装しないと期待通りに動かない。
  • skip + limit の順序:
    • ページングは必ず skip → limit の順。逆だと結果が変わる。
  • 大量データでの distinct:
    • 全件を保持して判定するためメモリ負荷が大きい。必要なら DB 側で distinct する、またはチャンク処理を検討。
  • 無限ストリームで limit を忘れる:
    • Stream.generateiterate は必ず limit/takeWhile を入れて有限化。

まとめ

  • distinct: 重複排除(equals/hashCode 基準)。
  • limit: 先頭から指定件数だけ残す。
  • skip: 先頭から指定件数を飛ばす。
  • 組み合わせ: ページングや部分抽出に最適。

👉 練習課題: 「商品リストから重複を除き、3ページ目(1ページ10件)の商品名を取得」してみると、distinct・skip・limit の流れが自然に理解できます。

タイトルとURLをコピーしました