Java でリストに重複要素があるかどうかをチェックする方法

JavaJavaBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験では、Java の List に重複する要素が含まれているかどうかを効率的にチェックする方法を学びます。HashSet データ構造を使用した一般的で効果的な手法を探ります。

まず、HashSet の要素の一意性を利用して、リストを反復処理しながら要素をセットに追加することで重複を検出するメソッドを実装します。セットにすでに要素が存在する場合、重複が見つかったことになります。その後、元のリストのサイズと、リストの要素で満たされた HashSet のサイズを比較することで、別のアプローチを学びます。最後に、null リストや空のリストを含むさまざまなシナリオで実装をテストし、堅牢性を確保します。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL java(("Java")) -.-> java/DataStructuresGroup(["Data Structures"]) java(("Java")) -.-> java/ObjectOrientedandAdvancedConceptsGroup(["Object-Oriented and Advanced Concepts"]) java/DataStructuresGroup -.-> java/arrays("Arrays") java/DataStructuresGroup -.-> java/collections_methods("Collections Methods") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/arraylist("ArrayList") java/ObjectOrientedandAdvancedConceptsGroup -.-> java/hashset("HashSet") subgraph Lab Skills java/arrays -.-> lab-559948{{"Java でリストに重複要素があるかどうかをチェックする方法"}} java/collections_methods -.-> lab-559948{{"Java でリストに重複要素があるかどうかをチェックする方法"}} java/arraylist -.-> lab-559948{{"Java でリストに重複要素があるかどうかをチェックする方法"}} java/hashset -.-> lab-559948{{"Java でリストに重複要素があるかどうかをチェックする方法"}} end

重複検出に HashSet を使用する

このステップでは、Java の HashSet を使用してコレクション内の重複要素を効率的に検出する方法を探ります。HashSet は Java コレクションフレームワークの一部で、一意の要素を格納するのに特に便利です。

まず、~/project ディレクトリに DuplicateDetector.java という名前の新しい Java ファイルを作成しましょう。これは、左側の WebIDE のファイルエクスプローラーを使用して行うことができます。~/project 領域で右クリックし、「New File」を選択して DuplicateDetector.java と入力します。

次に、コードエディターで DuplicateDetector.java ファイルを開き、以下のコードを追加します。

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class DuplicateDetector {

    public static boolean containsDuplicates(List<String> list) {
        // Create a HashSet to store unique elements
        Set<String> uniqueElements = new HashSet<>();

        // Iterate through the list
        for (String element : list) {
            // If the element is already in the HashSet, it's a duplicate
            if (uniqueElements.contains(element)) {
                return true; // Found a duplicate
            }
            // Otherwise, add the element to the HashSet
            uniqueElements.add(element);
        }

        // If the loop finishes without finding duplicates, return false
        return false;
    }

    public static void main(String[] args) {
        // Example usage
        List<String> myListWithDuplicates = new ArrayList<>();
        myListWithDuplicates.add("apple");
        myListWithDuplicates.add("banana");
        myListWithDuplicates.add("apple"); // Duplicate
        myListWithDuplicates.add("orange");

        List<String> myListWithoutDuplicates = new ArrayList<>();
        myListWithoutDuplicates.add("grape");
        myListWithoutDuplicates.add("mango");
        myListWithoutDuplicates.add("kiwi");

        System.out.println("List with duplicates: " + myListWithDuplicates);
        System.out.println("Contains duplicates? " + containsDuplicates(myListWithDuplicates)); // Expected: true

        System.out.println("\nList without duplicates: " + myListWithoutDuplicates);
        System.out.println("Contains duplicates? " + containsDuplicates(myListWithoutDuplicates)); // Expected: false
    }
}

このコードの重要な部分を理解しましょう。

  • import java.util.ArrayList;, import java.util.HashSet;, import java.util.List;, import java.util.Set;: これらの行は、Java コレクションフレームワークから必要なクラスをインポートします。
  • public static boolean containsDuplicates(List<String> list): これは、String オブジェクトの List を入力として受け取り、重複が含まれている場合は true を返し、そうでない場合は false を返すメソッドです。
  • Set<String> uniqueElements = new HashSet<>();: これは uniqueElements という名前の空の HashSet を作成します。HashSet は一意の要素のみを格納するように設計されています。
  • for (String element : list): このループは、入力 list の各 element を反復処理します。
  • if (uniqueElements.contains(element)): これは、現在の elementuniqueElements HashSet にすでに存在するかどうかをチェックします。存在する場合、重複が見つかったことになり、メソッドは true を返します。
  • uniqueElements.add(element);: 要素が HashSet にまだ存在しない場合、追加されます。HashSet は一意の要素のみを格納するため、すでに存在する要素を追加しても効果はありません。
  • return false;: ループが重複を見つけずに完了した場合、メソッドは false を返します。
  • main メソッドは、サンプルリストを使用して containsDuplicates メソッドを使用する方法を示しています。

DuplicateDetector.java ファイルを保存します(Ctrl+S または Cmd+S)。

次に、ターミナルでこのプログラムをコンパイルして実行しましょう。~/project ディレクトリにいることを確認してください。

コードをコンパイルします。

javac DuplicateDetector.java

コンパイルエラーがない場合、出力は表示されません。

次に、コンパイルされたコードを実行します。

java DuplicateDetector

以下のような出力が表示されるはずです。

List with duplicates: [apple, banana, apple, orange]
Contains duplicates? true

List without duplicates: [grape, mango, kiwi]
Contains duplicates? false

この出力は、containsDuplicates メソッドが重複のあるリストを正しく識別したことを確認しています。HashSet を使用することは、重複をチェックする効率的な方法です。なぜなら、HashSet 内に要素が存在するかどうかをチェックする(contains() を使用する)のは、平均的に非常に高速だからです。

リストのサイズとセットのサイズを比較する

前のステップでは、リストを反復処理して要素をセットに追加することで、HashSet を使用して重複をチェックしました。重複を検出するより簡単で、多くの場合、より効率的な方法は、元のリストのサイズと、そのリストから作成された HashSet のサイズを比較することです。

HashSet は一意の要素のみを格納することを思い出してください。リストに重複が含まれている場合、そのリストから作成された HashSet のサイズは、元のリストのサイズよりも小さくなります。重複がない場合、サイズは同じになります。

このアプローチを実装するために、DuplicateDetector.java ファイルを変更しましょう。コードエディターで ~/project/DuplicateDetector.java を開きます。

containsDuplicates メソッドを以下のコードに置き換えます。

    public static boolean containsDuplicates(List<String> list) {
        // Create a HashSet from the list
        Set<String> uniqueElements = new HashSet<>(list);

        // Compare the size of the list with the size of the HashSet
        return list.size() != uniqueElements.size();
    }

新しいコードでは以下のことが行われています。

  • Set<String> uniqueElements = new HashSet<>(list);: この行は、入力 list のすべての要素で HashSet を直接作成し、初期化します。HashSet は自動的に一意性を処理するため、リスト内の重複要素はセットに追加されません。
  • return list.size() != uniqueElements.size();: この行は、元の list の要素数 (list.size()) と HashSet の一意の要素数 (uniqueElements.size()) を比較します。サイズが異なる場合 (!=)、リストに重複があったことを意味し、メソッドは true を返します。サイズが同じ場合、重複はなく、メソッドは false を返します。

main メソッドは、すでに containsDuplicates メソッドを呼び出しているため、同じままにすることができます。

DuplicateDetector.java ファイルを保存します(Ctrl+S または Cmd+S)。

次に、変更したプログラムをコンパイルして実行しましょう。ターミナルで ~/project ディレクトリにいることを確認してください。

コードをコンパイルします。

javac DuplicateDetector.java

コンパイルされたコードを実行します。

java DuplicateDetector

前と同じ出力が表示されるはずです。

List with duplicates: [apple, banana, apple, orange]
Contains duplicates? true

List without duplicates: [grape, mango, kiwi]
Contains duplicates? false

これは、サイズ比較を使用した新しい、より簡単な重複検出方法が正しく機能することを確認しています。このアプローチは一般的により簡潔で、特に大きなリストの場合、1 つずつ反復処理して包含をチェックするよりも効率的です。

空リストと null リストでテストする

実際のプログラミングでは、リストが空である場合や null である場合などのエッジケースを考慮することが重要です。現在の containsDuplicates メソッドは要素のあるリストに対してはうまく機能しますが、空のリストや null のリストを渡した場合はどうなるでしょうか。

~/project/DuplicateDetector.javamain メソッドにさらに例を追加してこれをテストしましょう。コードエディターでファイルを開き、既存のコードの後に以下の行を main メソッドに追加します。

        System.out.println("\nEmpty list: " + new ArrayList<>());
        System.out.println("Contains duplicates? " + containsDuplicates(new ArrayList<>())); // Expected: false

        List<String> nullList = null;
        System.out.println("\nNull list: " + nullList);
        // The following line will cause a NullPointerException if not handled
        // System.out.println("Contains duplicates? " + containsDuplicates(nullList));

ファイルを保存します(Ctrl+S または Cmd+S)。

次に、プログラムを再度コンパイルして実行します。

コンパイル:

javac DuplicateDetector.java

実行:

java DuplicateDetector

空のリストの出力が表示されるはずです。

List with duplicates: [apple, banana, apple, orange]
Contains duplicates? true

List without duplicates: [grape, mango, kiwi]
Contains duplicates? false

Empty list: []
Contains duplicates? false

空のリストの出力は正しいです。空のリストには重複がありません。

ただし、System.out.println("Contains duplicates? " + containsDuplicates(nullList)); の行のコメントを外してコンパイルして実行すると、NullPointerException が発生します。これは、null のリストから HashSet を作成しようとしているためで、これは許可されていません。

containsDuplicates メソッドをより堅牢にするために、入力リストが null の場合を処理する必要があります。メソッドの冒頭にチェックを追加することができます。

~/project/DuplicateDetector.javacontainsDuplicates メソッドを変更して、null チェックを含めます。

    public static boolean containsDuplicates(List<String> list) {
        // Handle null input
        if (list == null) {
            return false; // A null list does not contain duplicates
        }

        // Create a HashSet from the list
        Set<String> uniqueElements = new HashSet<>(list);

        // Compare the size of the list with the size of the HashSet
        return list.size() != uniqueElements.size();
    }

次に、main メソッドで null リストをテストする行のコメントを外します。

        List<String> nullList = null;
        System.out.println("\nNull list: " + nullList);
        System.out.println("Contains duplicates? " + containsDuplicates(nullList)); // Expected: false

ファイルを保存します(Ctrl+S または Cmd+S)。

最後に一度、プログラムをコンパイルして実行します。

コンパイル:

javac DuplicateDetector.java

実行:

java DuplicateDetector

出力には、クラッシュすることなく null リストの結果が含まれるはずです。

List with duplicates: [apple, banana, apple, orange]
Contains duplicates? true

List without duplicates: [grape, mango, kiwi]
Contains duplicates? false

Empty list: []
Contains duplicates? false

Null list: null
Contains duplicates? false

null チェックを追加することで、containsDuplicates メソッドはより堅牢になり、null 入力を適切に処理できるようになりました。これは、予期しないエラーを防ぐための重要なプログラミングの実践です。

まとめ

この実験では、Java の List に重複要素が含まれているかどうかをチェックする方法を学びました。効率的な重複検出のために HashSet を使用する方法を調べました。リストを反復処理し、各要素を HashSet に追加しようとすることで、要素がすでに存在するかどうかをすばやく判断でき、重複を検出できます。

また、元のリストのサイズと、そのリストから作成された HashSet のサイズを比較することで、別の方法も学びました。サイズが異なる場合、重複が存在することを示します。最後に、堅牢性を確保するために、null リストと空のリストでメソッドをテストすることで、エッジケースを考慮しました。