はじめに
この実験では、Java であるリストが別のリストのすべての要素を含んでいるかどうかをチェックする方法を学びます。これは、コレクションを扱う際やデータセット間の関係を理解する際の基本的なタスクです。
Java コレクションフレームワークが提供する効率的な containsAll() メソッドを使って、素早く部分集合をチェックする方法を探ります。理解を深めるために、ループを使って手動でこのチェックを行う方法も学びます。最後に、空のリストや null リストなどのエッジケースでこれらのメソッドの動作をテストし、堅牢なコードを確保します。
containsAll() を使用した部分集合のチェック
このステップでは、Java の containsAll() メソッドを使って、あるリストが別のリストの部分集合であるかどうかをチェックする方法を探ります。これはコレクションを扱う際の一般的なタスクであり、containsAll() はこのチェックを行う便利な方法を提供します。
まず、~/project ディレクトリに SubsetCheck.java という名前の新しい Java ファイルを作成しましょう。左側の WebIDE ファイルエクスプローラーを使ってこれを行うことができます。~/project 領域で右クリックし、「New File」を選択して SubsetCheck.java と入力します。
次に、エディタで SubsetCheck.java ファイルを開き、以下のコードを追加します。
import java.util.ArrayList;
import java.util.List;
public class SubsetCheck {
public static void main(String[] args) {
// Create the main list
List<String> mainList = new ArrayList<>();
mainList.add("Apple");
mainList.add("Banana");
mainList.add("Cherry");
mainList.add("Date");
// Create a potential subset list
List<String> subList = new ArrayList<>();
subList.add("Banana");
subList.add("Cherry");
// Check if subList is a subset of mainList using containsAll()
boolean isSubset = mainList.containsAll(subList);
// Print the result
System.out.println("Main List: " + mainList);
System.out.println("Sub List: " + subList);
System.out.println("Is subList a subset of mainList? " + isSubset);
// Create another list that is not a subset
List<String> anotherList = new ArrayList<>();
anotherList.add("Banana");
anotherList.add("Grape"); // Grape is not in mainList
// Check if anotherList is a subset of mainList
boolean isAnotherSubset = mainList.containsAll(anotherList);
// Print the result for the second check
System.out.println("\nAnother List: " + anotherList);
System.out.println("Is anotherList a subset of mainList? " + isAnotherSubset);
}
}
コードを分解して説明しましょう。
- リストを扱うために、
java.utilパッケージからArrayListとListをインポートします。 mainListとsubListという 2 つのArrayListオブジェクトを作成します。- 両方のリストにいくつかの文字列要素を追加します。
- 重要な部分は
mainList.containsAll(subList)です。このメソッドは、mainListがsubListに含まれるすべての要素を含んでいるかどうかをチェックします。含んでいればtrueを返し、そうでなければfalseを返します。 - 結果をブール型の変数
isSubsetに格納し、それを出力します。 - 次に、
mainListに存在しない要素を含むanotherListを作成し、同じチェックを行って、部分集合ではない場合の結果を確認します。
SubsetCheck.java ファイルを保存します(Ctrl+S または Cmd+S)。
次に、WebIDE の下部にあるターミナルを開きます。~/project ディレクトリにいることを確認してください。そうでない場合は、cd ~/project コマンドを使って移動します。
javac コマンドを使って Java コードをコンパイルします。
javac SubsetCheck.java
コンパイルエラーがなければ、~/project ディレクトリに SubsetCheck.class ファイルが作成されるはずです。
最後に、java コマンドを使ってコンパイルされた Java プログラムを実行します。
java SubsetCheck
以下のような出力が表示されるはずです。
Main List: [Apple, Banana, Cherry, Date]
Sub List: [Banana, Cherry]
Is subList a subset of mainList? true
Another List: [Banana, Grape]
Is anotherList a subset of mainList? false
この出力は、subList のすべての要素が mainList に存在するため、subList が mainList の部分集合であることを確認しています。一方、「Grape」が mainList にないため、anotherList は部分集合ではありません。
手動ループで検証する
前のステップでは、部分集合をチェックするために便利な containsAll() メソッドを使用しました。containsAll() は効率的ですが、ループを使用して手動でこのチェックを行う方法を理解することは有益です。これにより、コレクションメソッドが内部でどのように動作するかについての理解が深まります。
SubsetCheck.java ファイルに、部分集合のチェックを手動で行う新しいメソッドを追加しましょう。WebIDE エディタで ~/project/SubsetCheck.java を開きます。
SubsetCheck クラス内で、main メソッドの外に以下のメソッドを追加します。
// Method to manually check if subList is a subset of mainList
public static boolean isSubsetManual(List<String> mainList, List<String> subList) {
// Iterate through each element in the subList
for (String element : subList) {
// If the mainList does NOT contain the current element from subList,
// then subList is not a subset, and we can return false immediately.
if (!mainList.contains(element)) {
return false;
}
}
// If we have checked all elements in subList and found them all in mainList,
// then subList is a subset.
return true;
}
この新しいメソッド isSubsetManual は、2 つのリストを入力として受け取ります。そして、subList 内の各 element をループで処理します。ループ内では、contains() メソッドを使用して、mainList が現在の element を含んでいるかどうかをチェックします。subList 内に mainList に含まれない要素が 1 つでも見つかった場合、すぐに subList は部分集合ではないと判断し、false を返します。ループが終了しても subList 内に mainList に欠けている要素が見つからない場合、すべての要素が存在することを意味し、メソッドは true を返します。
次に、main メソッドからこの新しいメソッドを呼び出し、その結果を containsAll() の結果と比較しましょう。SubsetCheck.java の main メソッドを変更して、isSubsetManual の呼び出しを含めます。
import java.util.ArrayList;
import java.util.List;
public class SubsetCheck {
public static void main(String[] args) {
// Create the main list
List<String> mainList = new ArrayList<>();
mainList.add("Apple");
mainList.add("Banana");
mainList.add("Cherry");
mainList.add("Date");
// Create a potential subset list
List<String> subList = new ArrayList<>();
subList.add("Banana");
subList.add("Cherry");
// Check if subList is a subset of mainList using containsAll()
boolean isSubsetContainsAll = mainList.containsAll(subList);
// Check if subList is a subset of mainList using manual loop
boolean isSubsetManualCheck = isSubsetManual(mainList, subList);
// Print the result
System.out.println("Main List: " + mainList);
System.out.println("Sub List: " + subList);
System.out.println("Is subList a subset of mainList (containsAll)? " + isSubsetContainsAll);
System.out.println("Is subList a subset of mainList (manual check)? " + isSubsetManualCheck);
// Create another list that is not a subset
List<String> anotherList = new ArrayList<>();
anotherList.add("Banana");
anotherList.add("Grape"); // Grape is not in mainList
// Check if anotherList is a subset of mainList using containsAll()
boolean isAnotherSubsetContainsAll = mainList.containsAll(anotherList);
// Check if anotherList is a subset of mainList using manual loop
boolean isAnotherSubsetManualCheck = isSubsetManual(mainList, anotherList);
// Print the result for the second check
System.out.println("\nAnother List: " + anotherList);
System.out.println("Is anotherList a subset of mainList (containsAll)? " + isAnotherSubsetContainsAll);
System.out.println("Is anotherList a subset of mainList (manual check)? " + isAnotherSubsetManualCheck);
}
// Method to manually check if subList is a subset of mainList
public static boolean isSubsetManual(List<String> mainList, List<String> subList) {
// Iterate through each element in the subList
for (String element : subList) {
// If the mainList does NOT contain the current element from subList,
// then subList is not a subset, and we can return false immediately.
if (!mainList.contains(element)) {
return false;
}
}
// If we have checked all elements in subList and found them all in mainList,
// then subList is a subset.
return true;
}
}
変更した SubsetCheck.java ファイルを保存します。
次に、ターミナルで更新されたコードをコンパイルします。
javac SubsetCheck.java
そして、プログラムを再度実行します。
java SubsetCheck
以下のような出力が表示され、containsAll() メソッドと手動ループメソッドの両方が同じ結果を生成することが示されます。
Main List: [Apple, Banana, Cherry, Date]
Sub List: [Banana, Cherry]
Is subList a subset of mainList (containsAll)? true
Is subList a subset of mainList (manual check)? true
Another List: [Banana, Grape]
Is anotherList a subset of mainList (containsAll)? false
Is anotherList a subset of mainList (manual check)? false
このステップでは、潜在的な部分集合を繰り返し処理し、メインリスト内に各要素が存在するかどうかをチェックすることで、containsAll() と同じ結果を得ることができることを示しています。containsAll() は、その簡潔さと Java ライブラリ内の潜在的なパフォーマンス最適化のため、一般的に推奨されますが、手動アプローチを理解することは学習にとって価値があります。
空リストと null リストでテストする
このステップでは、containsAll() メソッドと手動チェックメソッドが、空リストと null 値を扱う際にどのように動作するかを調べます。これらのエッジケースを理解することは、堅牢なコードを書くために重要です。
WebIDE エディタで ~/project/SubsetCheck.java ファイルを開きます。main メソッドにさらにテストケースを追加します。
main メソッドを変更して、空リストと null リストを使ったチェックを含めます。
import java.util.ArrayList;
import java.util.List;
public class SubsetCheck {
public static void main(String[] args) {
// Create the main list
List<String> mainList = new ArrayList<>();
mainList.add("Apple");
mainList.add("Banana");
mainList.add("Cherry");
mainList.add("Date");
// Create a potential subset list
List<String> subList = new ArrayList<>();
subList.add("Banana");
subList.add("Cherry");
// Check if subList is a subset of mainList using containsAll()
boolean isSubsetContainsAll = mainList.containsAll(subList);
// Check if subList is a subset of mainList using manual loop
boolean isSubsetManualCheck = isSubsetManual(mainList, subList);
// Print the result
System.out.println("Main List: " + mainList);
System.out.println("Sub List: " + subList);
System.out.println("Is subList a subset of mainList (containsAll)? " + isSubsetContainsAll);
System.out.println("Is subList a subset of mainList (manual check)? " + isSubsetManualCheck);
// Create another list that is not a subset
List<String> anotherList = new ArrayList<>();
anotherList.add("Banana");
anotherList.add("Grape"); // Grape is not in mainList
// Check if anotherList is a subset of mainList using containsAll()
boolean isAnotherSubsetContainsAll = mainList.containsAll(anotherList);
// Check if anotherList is a subset of mainList using manual loop
boolean isAnotherSubsetManualCheck = isSubsetManual(mainList, anotherList);
// Print the result for the second check
System.out.println("\nAnother List: " + anotherList);
System.out.println("Is anotherList a subset of mainList (containsAll)? " + isAnotherSubsetContainsAll);
System.out.println("Is anotherList a subset of mainList (manual check)? " + isAnotherSubsetManualCheck);
// --- Test with Empty Lists ---
// Create an empty list
List<String> emptyList = new ArrayList<>();
// Check if emptyList is a subset of mainList
boolean isEmptySubsetContainsAll = mainList.containsAll(emptyList);
boolean isEmptySubsetManualCheck = isSubsetManual(mainList, emptyList);
System.out.println("\nEmpty List: " + emptyList);
System.out.println("Is emptyList a subset of mainList (containsAll)? " + isEmptySubsetContainsAll);
System.out.println("Is emptyList a subset of mainList (manual check)? " + isEmptySubsetManualCheck);
// Check if mainList is a subset of emptyList (should be false unless mainList is also empty)
boolean isMainSubsetEmptyContainsAll = emptyList.containsAll(mainList);
boolean isMainSubsetEmptyManualCheck = isSubsetManual(emptyList, mainList);
System.out.println("Is mainList a subset of emptyList (containsAll)? " + isMainSubsetEmptyContainsAll);
System.out.println("Is mainList a subset of emptyList (manual check)? " + isMainSubsetEmptyManualCheck);
// --- Test with Null List ---
// Create a null list
List<String> nullList = null;
// Check with nullList using containsAll()
System.out.println("\nNull List: " + nullList);
try {
boolean isNullSubsetContainsAll = mainList.containsAll(nullList);
System.out.println("Is nullList a subset of mainList (containsAll)? " + isNullSubsetContainsAll);
} catch (NullPointerException e) {
System.out.println("Checking with nullList using containsAll() resulted in: " + e);
}
// Check with nullList using manual loop
try {
boolean isNullSubsetManualCheck = isSubsetManual(mainList, nullList);
System.out.println("Is nullList a subset of mainList (manual check)? " + isNullSubsetManualCheck);
} catch (NullPointerException e) {
System.out.println("Checking with nullList using manual check resulted in: " + e);
}
}
// Method to manually check if subList is a subset of mainList
public static boolean isSubsetManual(List<String> mainList, List<String> subList) {
// Add a check for null subList in the manual method
if (subList == null) {
throw new NullPointerException("Sub list cannot be null for manual check.");
}
// Iterate through each element in the subList
for (String element : subList) {
// If the mainList does NOT contain the current element from subList,
// then subList is not a subset, and we can return false immediately.
if (!mainList.contains(element)) {
return false;
}
}
// If we have checked all elements in subList and found them all in mainList,
// then subList is a subset.
return true;
}
}
emptyList と nullList を使ったテストセクションを追加しました。nullList のテストでは、呼び出しを try-catch ブロックで囲んでいることに注意してください。これは、null オブジェクトに対してメソッドを呼び出そうとすると(例えば mainList.containsAll(nullList))、NullPointerException が発生するためです。手動メソッドでも subList が null の場合を処理する必要があるので、isSubsetManual の冒頭にチェックを追加しました。
変更した SubsetCheck.java ファイルを保存します。
ターミナルで更新されたコードをコンパイルします。
javac SubsetCheck.java
そして、プログラムを再度実行します。
java SubsetCheck
以下のような出力が表示されるはずです。
Main List: [Apple, Banana, Cherry, Date]
Sub List: [Banana, Cherry]
Is subList a subset of mainList (containsAll)? true
Is subList a subset of mainList (manual check)? true
Another List: [Banana, Grape]
Is anotherList a subset of mainList (containsAll)? false
Is anotherList a subset of mainList (manual check)? false
Empty List: []
Is emptyList a subset of mainList (containsAll)? true
Is emptyList a subset of mainList (manual check)? true
Is mainList a subset of emptyList (containsAll)? false
Is mainList a subset of emptyList (manual check)? false
Null List: null
Checking with nullList using containsAll() resulted in: java.lang.NullPointerException
Checking with nullList using manual check resulted in: java.lang.NullPointerException: Sub list cannot be null for manual check.
出力から、以下のことがわかります。
- 空リストは、どんなリスト(他の空リストを含む)の部分集合と見なされます。
containsAll()と手動メソッドの両方がこれを正しく識別します。 - 空でないリストは、空リストの部分集合ではありません。
nullリストをcontainsAll()または手動メソッド(nullチェックなし)に渡すと、NullPointerExceptionが発生します。これは、コード内で潜在的なnull値を処理する重要性を強調しています。
このステップで、Java リストの部分集合をチェックする探索は終了です。組み込みの containsAll() メソッドの使い方、手動でチェックする方法、およびこれらのメソッドが空リストと null リストでどのように動作するかを学びました。
まとめ
この実験では、Java であるリストが別のリストのすべての要素を含んでいるかどうかをチェックする方法を学びました。主に Collection インターフェースが提供する便利な containsAll() メソッドの使用に焦点を当てました。
サンプルリストを使って containsAll() の使い方を示し、部分集合の場合と部分集合でない場合の両方における動作を確認しました。このメソッドは、この一般的なリスト比較タスクを行うための簡潔で効率的な方法を提供します。



