【News】List入門:条件に合う要素だけ取り出すフィルタリング入門

こんにちは、バナナドリームです。

前回はListのループ処理と値の加工・変換について解説しました。
今回は「条件に合う要素だけを取り出したい」というフィルタリングがテーマです。

nullの除外から数値条件での絞り込みまで、実務でよく使うパターンを順に見ていきましょう。

フィルタリングとは?

Listの中には、「使いたい要素」と「使いたくない要素」が混在していることがよくあります。
例えば、nullや空文字が含まれるデータ、一定の条件を満たさない数値、不要なステータスのレコードなどです。

こうした不要な要素を取り除いて、条件に合うものだけを別のListに集める操作が「フィルタリング」です。

基本パターン:if文で条件を判定しながら絞り込む

まず最もシンプルな方法から見てみましょう。foreachループの中でif文を使い、条件を満たす要素だけを新しいListに追加する方法です。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> evens = new ArrayList<>();

for (int num : numbers) {
    if (num % 2 == 0) {
        evens.add(num);
    }
}
System.out.println(evens); // → [2, 4, 6, 8, 10]

ポイントはシンプルで、「条件に合うものだけ add() する」だけです。元のListはそのまま残るため、加工前のデータを保持しておきたい場合にも使いやすい書き方です。

nullと空文字を除外する

実務でよく遭遇するのが、nullや空文字が混ざったListのクリーニングです。そのまま処理してしまうと NullPointerException や意図しない表示につながることがあります。

List<String> names = Arrays.asList("Taro", null, "Hanako", "", "Jiro", null);
List<String> cleaned = new ArrayList<>();

for (String name : names) {
    if (name != null && !name.isEmpty()) {
        cleaned.add(name);
    }
}
System.out.println(cleaned); // → [Taro, Hanako, Jiro]

name != null で null チェック、!name.isEmpty() で空文字チェックを同時に行っています。この2つをセットで書く習慣をつけておくと、文字列処理でのバグを防ぎやすくなります。

注意点: name != null が false の場合、後続の !name.isEmpty() は評価されません。

そのため、必ず null チェックを先に書きましょう。

!name.isEmpty() を先に書くと、name が null のときに NullPointerException が発生します。

文字列の部分一致でフィルタリングする

「特定のキーワードを含む要素だけ取り出したい」という場面にも頻繁に出くわします。contains() メソッドを使うと、部分一致での絞り込みが簡単に書けます。

List<String> products = Arrays.asList("リンゴジュース", "オレンジゼリー", "バナナジュース", "メロンパン");
List<String> juices = new ArrayList<>();

for (String product : products) {
    if (product.contains("ジュース")) {
        juices.add(product);
    }
}
System.out.println(juices); // → [リンゴジュース, バナナジュース]

検索機能やカテゴリ絞り込みなど、ユーザー入力との組み合わせでも同じ考え方が使えます。

数値の範囲条件でフィルタリングする

数値のListから特定の範囲だけを取り出したい場合も同じ構造です。比較演算子(>=、<=、< など)をif文に組み合わせます。

List<Integer> scores = Arrays.asList(45, 72, 88, 33, 65, 90, 55);
List<Integer> passing = new ArrayList<>();

for (int score : scores) {
    if (score >= 60) {
        passing.add(score);
    }
}
System.out.println(passing); // → [72, 88, 65, 90]

「60点以上のみ合格」「在庫が5個以上のみ表示」など、実務データの絞り込みに直結する書き方です。

複数条件を組み合わせる

条件が複数あるときは &&(AND)や ||(OR)で組み合わせます。

List<String> items = Arrays.asList("apple", "apricot", "banana", "avocado", "blueberry");
List<String> result = new ArrayList<>();

for (String item : items) {
    if (item.startsWith("a") && item.length() >= 6) {
        result.add(item);
    }
}
System.out.println(result); // → [apricot, avocado]

「aから始まる、かつ6文字以上」という2つの条件を同時に満たすものだけを絞り込んでいます。
条件が増えるほど読みにくくなる傾向があるため、条件が3つ以上になる場合は変数名や改行でわかりやすく整理する工夫も大切です。

Stream APIを使ったフィルタリング

前回も少し触れましたが、Java 8以降ではStream APIの filter() を使うと、同じ処理をよりコンパクトに書けます。

import java.util.stream.Collectors;

List<Integer> scores = Arrays.asList(45, 72, 88, 33, 65, 90, 55);

List<Integer> passing = scores.stream()
    .filter(score -> score >= 60)
    .collect(Collectors.toList());

System.out.println(passing); // → [72, 88, 65, 90]

filter() に渡しているのはラムダ式で、「各要素に対して条件を評価し、trueのものだけ通す」という動きをします。処理の流れが左から右へ読める点が直感的です。
ただし、ループとStream APIの使い分けは状況次第です。初心者のうちはforループの構造をしっかり理解したうえで使うと、Streamが「何をやっているか」も自然とわかるようになります。

まとめ

・フィルタリングの基本は「foreachループ + if文 + add()」の組み合わせ
・nullと空文字の除外はセットで書くクセをつけると安全
・contains()、startsWith()、比較演算子など、条件の種類によって使うメソッドを選ぶ
・複数条件は && や || で組み合わせる
・慣れてきたらStream APIの filter() も選択肢に

次回:「ListをMapに変換する基本:キーと値のペアで管理しよう」

Listで管理していたデータを、後から「名前で引きたい」「IDで引きたい」という場面が出てきたとき、Mapへの変換が役立ちます。
次回はListからMapを作る基本的なパターンを解説します。

有限会社バナナドリーム

千葉県浦安市を拠点に、Javaを中心としたシステム開発からITコンサルタント、Webサイト制作まで幅広く手がけるシステム開発会社です。
開発・実装からアフターフォローまで一貫して対応し、お客様の課題に寄り添ったきめ細やかなサービスを提供しています。

「やさしさがつなぐ、人と未来と技術。」を掲げ、技術力だけでなく人と人とのつながりを大切にした経営を実践。
社員一人ひとりの個性を尊重し、30名規模を上限とした少数精鋭体制のもと、社員・顧客・地域社会のすべてと良好な関係を築くことを理念としています。
「Realize Dream ~夢は実現する為にある~」という言葉のもと、関わるすべての人の夢の実現をサポートし続けます。

お問い合わせはこちら