Java でコレクションに重複要素が含まれているかどうかをチェックする方法

JavaJavaBeginner
今すぐ練習

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

はじめに

この実験では、Java コレクション内の重複要素を効率的にチェックする方法を学びます。Java コレクションフレームワークの強力なツールである 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-559941{{"Java でコレクションに重複要素が含まれているかどうかをチェックする方法"}} java/collections_methods -.-> lab-559941{{"Java でコレクションに重複要素が含まれているかどうかをチェックする方法"}} java/arraylist -.-> lab-559941{{"Java でコレクションに重複要素が含まれているかどうかをチェックする方法"}} java/hashset -.-> lab-559941{{"Java でコレクションに重複要素が含まれているかどうかをチェックする方法"}} end

HashSet を使った重複チェック

このステップでは、Java の HashSet を使ってコレクション内の重複要素を効率的にチェックする方法を探ります。HashSet は Java コレクションフレームワークの一部で、一意の要素を格納し、非常に高速な検索が可能なため特に便利です。

まず、~/project ディレクトリに DuplicateCheck.java という名前の新しい Java ファイルを作成しましょう。WebIDE のファイルエクスプローラーで、ファイルリストエリアを右クリックして「New File」を選択し、DuplicateCheck.java と入力することで作成できます。

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

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

public class DuplicateCheck {

    public static void main(String[] args) {
        // Create a list with some duplicate elements
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Alice"); // Duplicate
        names.add("Charlie");
        names.add("Bob"); // Duplicate

        System.out.println("Original List: " + names);

        // Use a HashSet to find duplicates
        Set<String> uniqueNames = new HashSet<>();
        Set<String> duplicates = new HashSet<>();

        for (String name : names) {
            if (!uniqueNames.add(name)) {
                // If add returns false, the element is already in the set
                duplicates.add(name);
            }
        }

        System.out.println("Duplicates found: " + duplicates);
    }
}

このコードの新しい部分を分解してみましょう。

  • import java.util.ArrayList;, import java.util.HashSet;, import java.util.List;, import java.util.Set;: これらの行は、リストとセットを操作するために Java ユーティリティライブラリから必要なクラスをインポートします。
  • List<String> names = new ArrayList<>();: これは String オブジェクトを保持できる List である names を作成します。List インターフェースの具体的な実装として ArrayList を使用しています。
  • names.add(...): これは names リストに要素を追加します。「Alice」と「Bob」が 2 回追加されていることに注意してください。
  • Set<String> uniqueNames = new HashSet<>();: これは HashSet 実装を使用して uniqueNames という Set を作成します。Set は一意の要素のみを含むことを保証します。
  • Set<String> duplicates = new HashSet<>();: これは見つかった重複要素を格納するための別の Set を作成します。
  • for (String name : names): これは names リスト内の各 name を反復処理する for-each ループです。
  • if (!uniqueNames.add(name)): HashSetadd() メソッドは、要素が正常に追加された場合(つまり、セット内にまだ存在しなかった場合)は true を返し、要素がすでに存在する場合は false を返します。! は結果を反転させるため、if ブロック内のコードは add()false を返すとき、つまり重複があるときにのみ実行されます。
  • duplicates.add(name);: 重複が見つかった場合、それを duplicates セットに追加します。

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

次に、WebIDE の下部にあるターミナルを開きます。~/project ディレクトリにいることを確認してください。pwd と入力して Enter キーを押すことで確認できます。出力は /home/labex/project であるはずです。

javac コマンドを使用して Java プログラムをコンパイルします。

javac DuplicateCheck.java

エラーがなければ、何も出力されないはずです。これはコンパイルが成功し、~/project ディレクトリに DuplicateCheck.class ファイルが作成されたことを意味します。ls コマンドを実行することで確認できます。

最後に、java コマンドを使用してコンパイルされた Java プログラムを実行します。

java DuplicateCheck

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

Original List: [Alice, Bob, Alice, Charlie, Bob]
Duplicates found: [Alice, Bob]

HashSet は挿入順序を保持しないため、「Duplicates found」の出力における要素の順序は異なる場合があります。

あなたは HashSet を使ってリスト内の重複要素を正常に特定することができました!

コレクションとセットのサイズを比較する

前のステップでは、HashSet を使って重複要素を見つけました。Set の重要な特性は、一意の要素のみを格納することです。つまり、Set に重複要素を追加すると、各要素のインスタンスは 1 つだけ保持されます。この特性は、リストから重複を削除するなどのタスクに非常に便利です。

このステップでは、元のリスト(重複要素を含む可能性があります)のサイズと、そのリストから作成された HashSet(一意の要素のみを含みます)のサイズを比較することで、この特性を示すように DuplicateCheck.java プログラムを修正します。

WebIDE のコードエディターで DuplicateCheck.java ファイルを開きます。

main メソッドを以下のように修正します。

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

public class DuplicateCheck {

    public static void main(String[] args) {
        // Create a list with some duplicate elements
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add("Alice"); // Duplicate
        names.add("Charlie");
        names.add("Bob"); // Duplicate
        names.add("David");

        System.out.println("Original List: " + names);
        System.out.println("Size of Original List: " + names.size());

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

        System.out.println("Set created from List: " + uniqueNamesSet);
        System.out.println("Size of Set: " + uniqueNamesSet.size());

        // The difference in size tells us how many duplicates were removed
        int duplicatesCount = names.size() - uniqueNamesSet.size();
        System.out.println("Number of duplicates (excluding first occurrence): " + duplicatesCount);
    }
}

追加または変更した部分は次のとおりです。

  • names リストに別の名前「David」を追加して、少し大きなリストにしました。
  • System.out.println("Size of Original List: " + names.size());: size() メソッドを使って元のリストのサイズを出力します。
  • Set<String> uniqueNamesSet = new HashSet<>(names);: これは別の Collection(ここでは ArrayList)から直接 HashSet を作成する便利な方法です。このようにすると、HashSet は自動的にリストのすべての要素を追加し、Set であるため、重複要素は破棄されます。
  • System.out.println("Size of Set: " + uniqueNamesSet.size());: HashSet のサイズを出力します。このサイズは一意の要素の数を表します。
  • int duplicatesCount = names.size() - uniqueNamesSet.size();: リストのサイズとセットのサイズの差を計算します。この差は、(最初の出現を除いた)重複要素の数を示します。

修正した DuplicateCheck.java ファイルを保存します。

次に、ターミナルでプログラムを再度コンパイルします。

javac DuplicateCheck.java

コンパイルが成功したら、プログラムを実行します。

java DuplicateCheck

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

Original List: [Alice, Bob, Alice, Charlie, Bob, David]
Size of Original List: 6
Set created from List: [Alice, Bob, Charlie, David]
Size of Set: 4
Number of duplicates (excluding first occurrence): 2

元のリストのサイズは 6 ですが、それから作成された HashSet のサイズは 4 であることに注意してください。差(6 - 4 = 2)は、2 つの重複名(「Alice」と「Bob」が最初の出現後にそれぞれ 1 回ずつ登場した)があったことを正しく示しています。

これは、HashSet を使ってコレクション内の一意の要素の数や重複要素の数を簡単に見つけることができることを示しています。

ヌル要素でテストする

前のステップでは、HashSet が非ヌルの重複要素をどのように扱うかを見てきました。今度は、null 要素を追加しようとしたときの HashSet の動作を調べてみましょう。コレクションが null をどのように扱うかを理解することは重要です。なぜなら、注意深く扱わないと、予期しない動作やエラーにつながることがあるからです。

HashSet は 1 つの null 要素を許可します。null を複数回追加しようとすると、最初の null のみが格納されます。

これをテストするために、DuplicateCheck.java プログラムをもう一度修正しましょう。

WebIDE のコードエディターで DuplicateCheck.java ファイルを開きます。

main メソッドを修正して、リストに null 値を含めます。

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

public class DuplicateCheck {

    public static void main(String[] args) {
        // Create a list with some duplicate and null elements
        List<String> names = new ArrayList<>();
        names.add("Alice");
        names.add("Bob");
        names.add(null); // Add null
        names.add("Alice"); // Duplicate
        names.add("Charlie");
        names.add(null); // Add null again
        names.add("Bob"); // Duplicate
        names.add("David");
        names.add(null); // Add null a third time

        System.out.println("Original List: " + names);
        System.out.println("Size of Original List: " + names.size());

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

        System.out.println("Set created from List: " + uniqueNamesSet);
        System.out.println("Size of Set: " + uniqueNamesSet.size());

        // The difference in size tells us how many duplicates were removed
        // Note: This calculation is less straightforward with nulls and duplicates combined
        // int duplicatesCount = names.size() - uniqueNamesSet.size();
        // System.out.println("Number of duplicates (excluding first occurrence): " + duplicatesCount);
    }
}

ここでは、names リストに複数回 null を追加しています。また、null が含まれる場合、重複数の計算があまり意味を持たなくなるため、重複数の計算部分をコメントアウトしています。今回は null を含めたセットの動作に焦点を当てています。

修正した DuplicateCheck.java ファイルを保存します。

ターミナルでプログラムをコンパイルします。

javac DuplicateCheck.java

コンパイルが成功したら、プログラムを実行します。

java DuplicateCheck

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

Original List: [Alice, Bob, null, Alice, Charlie, null, Bob, David, null]
Size of Original List: 9
Set created from List: [null, Alice, Bob, Charlie, David]
Size of Set: 5

出力を見てみましょう。

  • Original List には、複数の null 値を含むすべての要素が表示されています。そのサイズは 9 です。
  • Set created from List には一意の要素のみが含まれています。リストに複数回 null が追加されていても、セット内では null が 1 回だけ表示されていることに注意してください。セットのサイズは 5(Alice、Bob、Charlie、David、および null)です。

これにより、HashSet が 1 つの null 要素を許可し、それ以降の null の追加を他の要素と同じように重複として扱うことが確認できます。

これで、HashSetnull 要素をどのように扱うかを正常にテストできました。これで、HashSet を使った重複チェックと、一意の要素および null 要素に対する動作の調査は終了です。

まとめ

この実験では、Java のコレクション内の重複要素を HashSet を使って効率的にチェックする方法を学びました。重複要素を含む List を作成し、それを反復処理して、各要素を HashSet に追加しようとしました。add() メソッドの戻り値をチェックすることで、要素がすでに存在する場合は false を返すため、重複要素を識別して別の HashSet に収集することができました。この方法は、HashSet の一意の要素特性と高速な検索機能を利用して、効果的な重複検出を行います。