How to Find an Element in a List with Java – 如何用Java查找列表中的一个元素

最后修改: 2018年 4月 28日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Finding an element in a list is a very common task we come across as developers.

在一个列表中寻找一个元素是我们作为开发者非常常见的任务。

In this quick tutorial, we’ll cover different ways we can do this with Java.

在这个快速教程中,我们将介绍用Java做到这一点的不同方法。

2. Setup

2.设置

First let’s start by defining a Customer POJO:

首先让我们从定义一个Customer POJO开始。

public class Customer {

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

Then an ArrayList of customers:

然后是一个ArrayList的客户。

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

Note that we’ve overridden hashCode and equals in our Customer class.

注意,我们已经在我们的Customer类中覆盖了hashCodeequals

Based on our current implementation of equals, two Customer objects with the same id will be considered equal.

基于我们目前对equals的实现,两个具有相同idCustomer对象将被视为相等。

We’ll use this list of customers along the way.

我们将沿途使用这个客户的名单。

3. Using Java API

3.使用Java API

Java itself provides several ways of finding an item in a list:

Java本身提供了几种在列表中寻找项目的方法。

  • The contains method
  • The indexOf method
  • An ad-hoc for loop
  • The Stream API

3.1. contains()

3.1.contains()

List exposes a method called contains:

List暴露了一个名为contains的方法。

boolean contains(Object element)

As the name suggests, this method returns true if the list contains the specified element, and returns false otherwise. 

顾名思义,如果列表包含指定的元素,该方法返回true,否则返回 false

So when we need to check if a specific item exists in our list, we can:

因此,当我们需要检查一个特定项目是否存在于我们的列表中时,我们可以。

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

3.2. indexOf()

3.2.indexOf()

indexOf is another useful method for finding elements:

indexOf是另一种寻找元素的有用方法。

int indexOf(Object element)

This method returns the index of the first occurrence of the specified element in the given list, or -1 if the list doesn’t contain the element.

该方法返回指定的元素在给定列表中第一次出现的索引,如果列表中不包含该元素,则返回-1。

So logically, if this method returns anything other than -1, we know that the list contains the element:

所以从逻辑上讲,如果这个方法的返回值不是-1,我们就知道这个列表包含了这个元素。

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

The main advantage of using this method is that it can tell us the position of the specified element in the given list.

使用这种方法的主要优点是它可以告诉我们指定元素在给定列表中的位置。

3.3. Basic Looping

3.3.基本循环

Now what if we want to do a field-based search for an element? For example, say we’re announcing a lottery and we need to declare a Customer with a specific name as the winner.

现在,如果我们想对一个元素做一个基于字段的搜索,该怎么办?例如,假设我们正在宣布一个抽奖活动,我们需要宣布一个具有特定名字客户为赢家。

For such field-based searches, we can turn to iteration.

对于这种基于领域的搜索,我们可以转向迭代。

A traditional way of iterating through a list is to use one of Java’s looping constructs. In each iteration, we compare the current item in the list with the element we’re looking for to see if it’s a match:

迭代列表的传统方法是使用Java的循环结构之一。在每次迭代中,我们将列表中的当前项与我们要找的元素进行比较,看它是否匹配。

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

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

Here the name refers to the name we are searching for in the given list of customers. This method returns the first Customer object in the list with a matching name, or null if no such Customer exists.

这里的name是指我们在给定的customers列表中搜索的名字。这个方法返回列表中第一个与name匹配的Customer对象,如果不存在这样的Customer,则返回null

3.4. Looping With an Iterator

3.4.用一个迭代器进行循环

Iterator is another way that we can traverse a list of items.

Iterator是另一种我们可以遍历一个项目列表的方式。

We can simply take our previous example and tweak it a bit:

我们可以简单地以我们之前的例子为例,对其进行一些调整。

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

Consequently, the behavior is the same as before.

因此,其行为与以前一样。

3.5. Java 8 Stream API

3.5 Java 8的Stream API

As of Java 8, we can also use the Stream API to find an element in a List.

从Java 8开始,我们也可以使用Stream API来查找List.中的一个元素。

To find an element matching specific criteria in a given list, we:

为了在一个给定的列表中找到符合特定标准的元素,我们。

  • invoke stream() on the list
  • call the filter() method with a proper Predicate
  • call the findAny() construct, which returns the first element that matches the filter predicate wrapped in an Optional if such an element exists
Customer james = customers.stream()
  .filter(customer -> "James".equals(customer.getName()))
  .findAny()
  .orElse(null);

For convenience, we default to null in case an Optional is empty, but this might not always be the best choice for every scenario.

为方便起见,在Optional为空的情况下,我们默认为null,但这不一定是每个场景的最佳选择。

4. Third-Party Libraries

4.第三方图书馆

Now, while the Stream API is more than sufficient, what should we do if we’re stuck on an earlier version of Java?

现在,虽然Stream API已经绰绰有余,但如果我们被困在早期版本的Java上,我们应该怎么办?

Fortunately, there are many third-party libraries like Google Guava and Apache Commons which we can use.

幸运的是,有许多第三方库,如Google Guava和Apache Commons,我们可以使用。

4.1. Google Guava

4.1.Google Guava

Google Guava provides functionality that is similar to what we can do with streams:

Google Guava提供的功能类似于我们可以用流来做的事情。

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

Just like with Stream API, we can optionally choose to return a default value instead of null:

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

The above code will pick the first element in the list if no match is found.

如果没有找到匹配的元素,上面的代码将挑选列表中的第一个元素。

Also, don’t forget that Guava throws a NullPointerException if either the list or the predicate is null.

另外,别忘了,如果列表或谓词是空的,Guava会抛出一个NullPointerException

4.2. Apache Commons

4.2.阿帕奇共享空间

We can find an element in almost the exact same way using Apache Commons:

我们可以使用Apache Commons以几乎完全相同的方式找到一个元素。

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

There are a couple of important differences though:

不过有几个重要的区别。

  1. Apache Commons just returns null if we pass a null list.
  2. It doesn’t provide default value functionality like Guava’s tryFind.

5. Conclusion

5.结论

In this article, we learned different ways of finding an element in a List, starting with quick existence checks and finishing with field-based searches.

在这篇文章中,我们学习了在List中寻找一个元素的不同方法,从快速的存在性检查开始,最后是基于字段的搜索。

We also looked at the third-party libraries Google Guava and Apache Commons as alternatives to the Java 8 Streams API.

我们还研究了第三方库Google GuavaApache Commons作为Java 8 Streams API的替代品。

Thanks for stopping by, and remember to check out all the sources for these examples over on GitHub.

谢谢你的光临,记得在GitHub上查看这些例子的所有来源