如何用Java查找列表中的一个元素
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"));
请注意,我们已经在我们的Customer类中重写了hashCode和equals。
基于我们目前对equals的实现,两个具有相同id的Customer对象将被认为是相等的。
我们将在此过程中使用此客户列表
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());
}
});
不过,有几个重要的区别。
- 如果我们传入一个null列表,Apache Commons只是返回null 。
- 它 不提供像Guava的tryFind.那样的默认值功能。
5.总结
在这篇文章中,我们学习了在List中寻找一个元素的不同方法,从快速的存在性检查开始,最后是基于字段的搜索。
我们还研究了第三方库Google Guava和Apache Commons作为Java 8 Streams API的替代方案。
谢谢你的光临,记得在GitHub上查看这些例子的所有来源。