Как найти элемент в списке с помощью Java

Как найти элемент в списке с помощью Java

1. обзор

Поиск элемента в списке - очень распространенная задача, с которой мы сталкиваемся как разработчики.

В этом кратком руководстве мы рассмотрим различные способы сделать это с помощью Java.

Дальнейшее чтение:

Проверка сортировки списка в Java

Изучите несколько алгоритмов для проверки, отсортирован ли список в Java.

Read more

Инициализация списка Java в одну строку

В этом кратком руководстве мы рассмотрим, как можно инициализировать список с помощью однострочных строк.

Read more

2. Настроить

Начнем с определения POJOCustomer:

public class Customer {

    private int id;
    private String name;

    // getters/setters, custom hashcode/equals
}

ИArrayList клиентов:

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

Обратите внимание, что мы переопределилиhashCode иequals в нашем классеCustomer.

На основе нашей текущей реализацииequals два объектаCustomer с одинаковымid будут считаться равными.

Мы будем использовать этот списокcustomers по пути.

3. Использование Java API

Сама Java предоставляет несколько способов поиска элемента в списке:

  • Методcontains

  • МетодindexOf 

  • An ad-hoc for loop и

  • Stream API

3.1. contains()с

List предоставляет метод под названиемcontains:

boolean contains(Object element)

Как следует из названия, этот метод возвращаетtrue, если список содержит указанныйelement,, и возвращаетfalse в противном случае. 

Поэтому, когда нам просто нужно проверить, существует ли определенный элемент в нашем списке, мы можем сделать:

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

3.2. indexOf()с

indexOf - еще один полезный метод поиска элементов:

int indexOf(Object element)

Этот метод возвращает индекс первого появления указанногоelement в данном списке или -1, если список не содержитelement.

Итак, логически, если этот метод возвращает что-либо кроме -1, мы знаем, что список содержит элемент:

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

Основное преимущество использования этого метода заключается в том, что он может сообщить нам положение указанного элемента в данном списке.

3.3. Основные циклы

Но что, если мы хотим выполнить поиск элемента на основе полей? Допустим, мы объявляем лотерею и нам нужно объявитьCustomer с конкретнымname в качестве победителя.

Для таких полевых поисков мы можем обратиться к итерации.

Традиционный способ перебора списка - использование одной из конструкцийJava’s looping. На каждой итерации мы сравниваем текущий элемент в списке с элементом, который ищем, чтобы проверить, совпадает ли он:

public Customer findUsingEnhancedForLoop(
  String name, List customers) {

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

Здесьname относится к имени, которое мы ищем в данном спискеcustomers. Этот метод возвращает первый объектCustomer в списке с совпадающимname иnull, если такогоCustomer не существует.

3.4. Цикл сIterator

Iterator - это еще один способ просмотра списка элементов.

Мы можем просто взять наш предыдущий пример и немного его настроить:

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

И поведение такое же, как и раньше.

3.5. API Java 8Stream

Начиная с Java 8, мы также можемuse the Stream API, чтобы найти элемент вList.

Чтобы найти элемент, соответствующий определенным критериям в данном списке, мы:

  • вызватьstream() в списке

  • вызвать методfilter() с правильнымPredicate

  • вызвать sconstructfindAny() , который возвращаетthe first element that matches the filter predicate wrapped in an Optional, если такой элемент существует **

Customer james = customers.stream()
  .filter(customer -> "James".equals(customer.getName()))
  .findAny()
  .orElse(null);

Для удобства мы по умолчанию используемnull в случае, еслиOptional пуст, но это не всегда может быть лучшим выбором для каждого сценария.

4. Сторонние библиотеки

Теперь, когда Stream API более чем достаточно,what should we do if we’re stuck on an earlier version of Java?

К счастью, есть много сторонних библиотек, таких как Google Guava и Apache Commons, которые мы можем использовать.

4.1. Google Guava

Google Guava предоставляет функциональность, аналогичную той, которую мы можем сделать с потоками:

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

Как и в случае с APIStream, при желании мы можем выбрать возврат значения по умолчанию вместоnull:

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

Приведенный выше код выберет первый элемент в списке, если совпадение не найдено.

И не забывайте, что Guava выдаетNullPointerException, если список или предикатnull.

4.2. Apache Commons

Мы можем найти элемент почти точно так же, используя Apache Commons:

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

Однако есть несколько важных отличий:

  1. Apache Commons просто возвращаетnull , если мы передаем списокnull

  2. Он  не предоставляет функциональные возможности значений по умолчанию, такие какtryFind в Guava.

5. Заключение

В этой статье мы узнали о различных способах поиска элемента вList, s, начиная с быстрой проверки существования и заканчивая поиском по полю.

Мы также рассмотрели сторонние библиотекиGoogle Guava иApache Commons как альтернативы API Java 8Streams.

Спасибо, что заглянули, и не забудьте проверить все исходники этих примеровover on GitHub.