如何用Java查找列表中的一个元素

评论 0 浏览 0 2018-04-29

1.概述

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

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

进一步的阅读。

在Java中检查一个列表是否被排序了

一条线上的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"));

请注意,我们已经在我们的Customer类中重写了hashCodeequals

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

我们将在此过程中使用此客户列表

3.使用Java API

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

  • contains方法
  • indexOf方法
  • 一个基本的for循环
  • StreamAPI

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是另一种寻找元素的有用方法。

int indexOf(Object element)

该方法返回指定的element在给定列表中第一次出现的索引,如果列表中不包含该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;
}

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

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

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

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

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 Java 8的Stream API

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

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

  • 在列表中调用stream()
  • 用一个适当的 Predicate 调用filter()方法。
  • 调用findAny() 结构,它返回第一个与过滤器谓词相匹配的元素,该元素被包裹在Optional中,如果这样的元素存在
    的话。
Customer james = customers.stream()
  .filter(customer -> "James".equals(customer.getName()))
  .findAny()
  .orElse(null);

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

4.第三方库

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

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

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

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

另外,别忘了,如果列表或predicate是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. 如果我们传入一个null列表,Apache Commons只是返回null
  2. 不提供像Guava的tryFind.那样的默认值功能。

5.总结

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

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

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

最后更新2023-10-23
0 个评论