1. 概要

リスト内の要素を見つけることは、開発者として遭遇する非常に一般的なタスクです。

このクイックチュートリアルでは、Javaを使用してこれを行うさまざまな方法について説明します。

2. 設定

まず、 CustomerPOJOを定義することから始めましょう。

public class Customer {

    private int id;
    private String name;
    
    // getters/setters, custom hashcode/equals
}

次に、顧客の ArrayList

List<Customer> customers = new ArrayList<>();
customers.add(new Customer(1, "Jack"));
customers.add(new Customer(2, "James"));
customers.add(new Customer(3, "Kelly"));

CustomerクラスのhashCodeequalsをオーバーライドしたことに注意してください。

equals の現在の実装に基づいて、同じidを持つ2つのCustomerオブジェクトは等しいと見なされます。

この顧客のリストを途中で使用します。

3. JavaAPIの使用

Java自体は、リスト内の項目を見つけるいくつかの方法を提供します。

  • containsメソッド
  • indexOfメソッド
  • アドホックforループ
  • ストリームAPI

3.1. contains()

List は、containsというメソッドを公開します。

boolean contains(Object element)

名前が示すように、このメソッドは、リストに指定された要素が含まれている場合は true を返し、そうでない場合はfalseを返します。

したがって、特定のアイテムがリストに存在するかどうかを確認する必要がある場合は、次のことができます。

Customer james = new Customer(2, "James");
if (customers.contains(james)) {
    // ...
}

3.2. indexOf()

indexOf は、要素を見つけるためのもう1つの便利な方法です。

int indexOf(Object element)

このメソッドは、指定されたリストで指定された要素が最初に出現するインデックスを返します。リストに要素が含まれていない場合は、-1を返します。

したがって、論理的には、このメソッドが-1以外のものを返す場合、リストに次の要素が含まれていることがわかります。

if(customers.indexOf(james) != -1) {
    // ...
}

この方法を使用する主な利点は、指定されたリスト内の指定された要素の位置を教えてくれることです。

3.3. 基本的なループ

では、要素のフィールドベースの検索を実行したい場合はどうでしょうか。 たとえば、宝くじを発表していて、特定のを持つ顧客を勝者として宣言する必要があるとします。

このようなフィールドベースの検索では、反復に目を向けることができます。

リストを反復処理する従来の方法は、Javaのlooping構造の1つを使用することです。 各反復で、リスト内の現在のアイテムを探している要素と比較して、一致するかどうかを確認します。

public Customer findUsingEnhancedForLoop(
  String name, List<Customer> customers) {

    for (Customer customer : customers) {
        if (customer.getName().equals(name)) {
            return customer;
        }
    }
    return null;
}

ここで、は、指定された顧客のリストで検索している名前を指します。 このメソッドは、一致するnameを持つリストの最初のCustomerオブジェクトを返します。そのようなCustomerが存在しない場合はnullを返します。

3.4. イテレータでループする

Iterator は、アイテムのリストをトラバースできるもう1つの方法です。

前の例を取り上げて、少し調整するだけです。

public Customer findUsingIterator(
  String name, List<Customer> customers) {
    Iterator<Customer> iterator = customers.iterator();
    while (iterator.hasNext()) {
        Customer customer = iterator.next();
        if (customer.getName().equals(name)) {
            return customer;
        }
    }
    return null;
}

したがって、動作は以前と同じです。

3.5. Java8ストリームAPI

Java 8以降、 Stream API を使用して、リスト内の要素を検索することもできます。

特定のリストで特定の基準に一致する要素を見つけるには、次のようにします。

  • リストのstream()を呼び出す
  • 適切な述語を使用してf ilter()メソッドを呼び出します。
  • findAny()コンストラクトを呼び出します。このコンストラクトは、そのような要素が存在する場合、Optionalでラップされたフィルター述語に一致する最初の要素を返します
Customer james = customers.stream()
  .filter(customer -> "James".equals(customer.getName()))
  .findAny()
  .orElse(null);

便宜上、オプションが空の場合、デフォルトで null に設定されますが、これがすべてのシナリオに最適であるとは限りません。

4. サードパーティのライブラリ

さて、Stream APIで十分ですが、以前のバージョンのJavaで立ち往生している場合は、どうすればよいですか?

幸い、GoogleGuavaやApacheCommonsなどのサードパーティライブラリを使用できます。

4.1. Google Guava

Google Guavaは、ストリームで実行できる機能と同様の機能を提供します。

Customer james = Iterables.tryFind(customers,
  new Predicate<Customer>() {
      public boolean apply(Customer customer) {
          return "James".equals(customer.getName());
      }
  }).orNull();

Stream APIの場合と同様に、オプションでnullの代わりにデフォルト値を返すことを選択できます。

Customer james = Iterables.tryFind(customers,
  new Predicate<Customer>() {
      public boolean apply(Customer customer) {
          return "James".equals(customer.getName());
      }
  }).or(customers.get(0));

上記のコードは、一致するものが見つからない場合、リストの最初の要素を選択します。

また、リストまたは述語のいずれかが null の場合、GuavaがNullPointerExceptionをスローすることを忘れないでください。

4.2. Apache Commons

Apache Commonsを使用すると、ほぼ同じ方法で要素を見つけることができます。

Customer james = IterableUtils.find(customers,
  new Predicate<Customer>() {
      public boolean evaluate(Customer customer) {
          return "James".equals(customer.getName());
      }
  });

ただし、いくつかの重要な違いがあります。

  1. Apache Commonsは、 null リストを渡すと、nullを返すだけです。
  2. It は、GuavaのtryFind。のようなデフォルト値の機能を提供しません。

5. 結論

この記事では、リスト内の要素を見つけるさまざまな方法を学びました。sは、存在チェックをすばやく実行し、フィールドベースの検索を終了します。

また、Java 8 Streams APIの代替として、サードパーティライブラリ GoogleGuavaおよびApacheCommonsも検討しました。

立ち寄っていただきありがとうございます。GitHubでこれらの例のすべてのソースを確認することを忘れないでください。