在 Java 中高效搜索 ArrayList 中的对象
本文介绍了如何在这里 Java 中搜索 ArrayList 特定对象中,重点是理解, contains() 该方法的局限性,并提供了一个基于循环的定制搜索解决方案。根据对象的属性(如产品名称),详细显示了如何根据对象的属性(如产品名称) ArrayList 寻找目标对象,并提供相关注意事项。
在 Java 中,ArrayList 用于存储对象集合的常用动态数组。当需要搜索时 ArrayList 当一个特定的对象是否存在时,通常会想到使用它 contains() 方法。但是,直接使用 contains() 找到具有特定属性的对象的方法(例如,根据产品名称找到) Product 对象)往往得不到预期的结果。 这是因为 ArrayList 的 contains() 默认使用该方法 equals() 比较对象的方法。 假如没有重写 equals() 方法,它引用比较对象,而不是对象的内容。
理解 contains() 方法的局限性
ArrayList 的 contains(Object o) 这种方法的工作原理是:遍历 ArrayList 并使用中间的每个元素 o.equals(element) 比较给定的对象 o 列表中的每个元素 element。 若找一个 element 使得 o.equals(element) 返回 true,则 contains() 方法返回 true;否则,返回 false。
默认情况下,Object 类的 equals() 该方法比较了对象的引用。这意味着只有当 o 和 element 指向内存中的同一对象时,o.equals(element) 才会返回 true。
立
在上述问题描述的代码中,ArrayList 存储的是 Product 试着使用类的对象 String 类型的 name 来调用 contains() 方法。 由于 String 对象和 Product 对象永远不会相等,所以对象永远不会相等 contains() 方法总是回来的 false。
使用循环进行自定义搜索
根据对象的属性(如产品名称) ArrayList 要找到目标对象,需要使用循环遍历 ArrayList,并手动比较每个对象的属性。
以下是如何通过循环和属性比较搜索的示例代码 ArrayList 中的 Product 对象:
import java.util.ArrayList; import java.util.Scanner; class Product { String name; int price; int id; Product(int i, String name, int price) { this.id = i; this.name = name; this.price = price; } } public class Test { public static void main(String[] args) { ArrayList<Product> al = new ArrayList<Product>(); al.add(new Product(1, "Samsung", 10000)); al.add(new Product(2, "Apple", 20000)); al.add(new Product(3, "Nokia", 30000)); al.add(new Product(4, "Sony", 40000)); al.add(new Product(5, "LG", 50000)); System.out.println("Enter the name of the product to search:"); Scanner sc = new Scanner(System.in); String name = sc.nextLine(); boolean found = false; for (Product p : al) { if (p.name.equals(name)) { System.out.println("Product found: " + p.id + " " + p.name + " " + p.price); found = true; break; // 找到第一个匹配项后退出循环 } } if (!found) { System.out.println("Product not found"); } } }代码解释:
- 循环遍历: 使用 for-each 循环遍历 ArrayList 中的每个 Product 对象。
- 属性比较: 对于每个 Product 对象 p,使用 p.name.equals(name) 将其 name 属性与用户输入 name 进行比较。
- 找到匹配项: 若找匹配的 Product 对象将打印产品信息并将其打印出来 found 标志设置为 true,然后使用 break 语句退出循环。
- 没有找到匹配项目: 若循环结束 found 标志仍然为 false,则说明 ArrayList 没有具有指定名称的。 Product 对象,打印 "Product not found"。
重写 equals() 方法 (可选)
另一种方法是重写 Product 类的 equals() 方法是根据产品名称进行比较。 如果重写了 equals() 该方法可直接使用 contains() 方法来查找 Product 对象。
class Product { String name; int price; int id; Product(int i, String name, int price) { this.id = i; this.name = name; this.price = price; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; Product product = (Product) obj; return name != null ? name.equals(product.name) : product.name == null; } @Override public int hashCode() { return name != null ? name.hashCode() : 0; } }注意事项:
- 如果重写了 equals() 强烈建议同时重写方法 hashCode() 保证方法 equals() 方法和 hashCode() 方法的一致性。 这是因为在 HashMap 和 HashSet 等基于哈希表的集合,hashCode() 该方法用于确定对象的存储位置。 如果 equals() 方法相等但 hashCode() 如果方法不相等,对象可能无法正确存储和检索。
修改后的 Test 类可以使用 contains 但是需要创建临时的方法 Product 对象用于比较:
import java.util.ArrayList; import java.util.Scanner; public class Test { public static void main(String[] args) { ArrayList<Product> al = new ArrayList<Product>(); al.add(new Product(1, "Samsung", 10000)); al.add(new Product(2, "Apple", 20000)); al.add(new Product(3, "Nokia", 30000)); al.add(new Product(4, "Sony", 40000)); al.add(new Product(5, "LG", 50000)); System.out.println("Enter the name of the product to search:"); Scanner sc = new Scanner(System.in); String name = sc.nextLine(); Product searchProduct = new Product(0, name, 0); // 创建临时Product对象 if (al.contains(searchProduct)) { System.out.println("Product found"); } else { System.out.println("Product not found"); } } }总结在 Java 中,使用 ArrayList 的 contains() 直接找到具有特定属性的对象的方法通常无法得到预期的结果。 这是因为 contains() 默认使用该方法 equals() 比较对象引用的方法。 为了根据对象的属性进行搜索,可以使用循环遍历 ArrayList 并手动比较每个对象的属性。 此外,还可以重写 equals() 为了实现自定义对象的逻辑,需要注意同时重写 hashCode() 方法。根据实际情况选择最合适的搜索方案,以提高代码的可读性和效率。
