Перейти к основному содержимому

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

· 5 мин. чтения

1. Обзор

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

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

2. Настройка

Сначала давайте начнем с определения Customer POJO:

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"));

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

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

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

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

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

  • Метод содержит _
  • Метод indexOf _
  • Специальный цикл for
  • Потоковый API _

3.1. содержит()

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

boolean contains(Object element)

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

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

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

3.2. индекс чего-либо()

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

int indexOf(Object element)

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

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

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

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

3.3. Базовый цикл

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

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

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

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

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

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

3.4. Зацикливание с помощью итератора

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

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

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. API потока Java 8

Начиная с Java 8, мы также можем использовать Stream API для поиска элемента в списке.

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

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

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

  • вызвать конструкцию findAny() , которая возвращает первый элемент, соответствующий предикату фильтра , завернутый в необязательный элемент, если такой элемент существует. **

    **

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

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

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

Теперь, когда Stream API более чем достаточно, что нам делать, если мы застряли на более ранней версии Java?

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

4.1. Google Гуава

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));

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

Кроме того, не забывайте, что Guava генерирует исключение NullPointerException , если список или предикат имеют значение null .

4.2. Апач Коммонс

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

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

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

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

5. Вывод

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

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

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