当前位置: 首页 > news >正文

Java ArrayList中按对象属性查找元素的正确姿势

本教程讨论Java 根据对象的特定属性(如产品名称),在ArrayList中找到元素的正确方法。它指出直接使用ArayList.contains()由于类型不匹配,与字符串参数无效。本文将通过迭代遍历列表和使用Java详细介绍 8 Stream API实现高效搜索,并提供相应的代码示例和注意事项。1. 理解 ArrayList.contains() 的局限性

arraylist在java中contains(object o)该方法用于判断列表中是否包含指定元素。其核心机制是通过使用每个元素的equals()方法来比较列表中的每个元素。如果你找到一个元素e,使o.equals(e)返回true时,contains()方法返回true。

然而,当自定义对象(如Product对象)存储在Arraylist中时,当我们尝试使用String类型的参数来调用contains()方法时,就会出现问题。Product对象永远不会等同于String对象(即productinstance.equals(searchString)将永远返回false),因为它们是不同类型的对象。因此,ArrayList.contains(String name)在这种情况下,总是返回false,无法实现根据产品名称搜索的目的。

考虑以下错误示例:

import java.util.*; 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 String toString() { return "Product{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + '}'; } } public class IncorrectSearchExample { public static void main(String[] args) { ArrayList<Product> al = new ArrayList<>(); al.add(new Product(1, "Samsung", 10000)); al.add(new Product(2, "Apple", 20000)); // ... 添加更多产品 Scanner sc = new Scanner(System.in); System.out.println("请输入要搜索的产品名称:"); String name = sc.nextLine(); // 错误的使用方法:将Product对象列表与String参数进行contains比较 if (al.contains(name)) { // 总是返回 false System.out.println("产品找到"); } else { System.out.println("产品未找到"); } sc.close(); } }

上述代码中的if (al.contains(name))行会永远找不到产品,因为它试图将String对象与Arraylist中的Product对象进行比较,而这两种类型之间没有equals()意义上的相等性。

2. 传统的迭代方法寻找元素

为了正确地根据对象的属性(如产品名称)找到Arraylist中的元素,我们需要手动检查每个对象的相应属性。这可以通过标准的for-each循环来实现。

立即学习“Java免费学习笔记(深入);

以下示例显示了如何通过传统迭代实现精确匹配和模糊匹配(包括):

import java.util.*; // 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 String toString() { return "Product{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + '}'; } } public class IterativeSearchExample { public static void main(String[] args) { ArrayList<Product> al = new ArrayList<>(); 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("现有产品列表:"); for (Product p : al) { System.out.println(p); } Scanner sc = new Scanner(System.in); // --- 精确匹配 --- System.out.println("请输入要搜索的产品名称 (精确匹配,忽略大小写):"); String searchNameExact = sc.nextLine(); Product foundProductExact = null; for (Product p : al) { // 使用equalsignoreCase()准确匹配,不区分大小写 if (p.name.equalsIgnoreCase(searchNameExact)) { foundProductExact = p; break; // 找到第一个匹配项后,可以退出循环 } } if (foundProductExact != null) { System.out.println("找到准确匹配的产品: " + foundProductExact); } else { System.out.println("未找到准确的匹配产品: " + searchNameExact); } // --- 模糊匹配 --- System.out.println("请输入要搜索的产品名称 (模糊匹配,忽略大小写):"); String searchNamePartial = sc.nextLine(); List<Product> foundProductsPartial = new ArrayList<>(); for (Product p : al) { // 将产品名称和搜索词转换成小写,然后使用contains()进行模糊匹配 if (p.name.toLowerCase().contains(searchNamePartial.toLowerCase())) { foundProductsPartial.add(p); } } if (!foundProductsPartial.isEmpty()) { System.out.println("找到模糊匹配产品:"); for (Product p : foundProductsPartial) { System.out.println(p); } } else { System.out.println("未找到模糊匹配产品: " + searchNamePartial); } sc.close(); } }

注意事项:

  • equalsIgnoreCase() 用于准确匹配,不区分大小写。
  • toLowerCase().contains(searchString.toLowerCase()) 用于模糊匹配,不区分大小写。
  • 如果只需要找到第一个匹配项,可以在找到后使用break语句提前退出循环,提高效率。

3. 使用 Java Stream API 查找元素 (Java 8+)

Java Streamm引入Stream API提供了一种更声明、更简单的方法来处理集合数据。它特别适用于过滤、映射和搜索。

import java.util.*; import java.util.stream.Collectors; // 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 String toString() { return "Product{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + '}'; } } public class StreamSearchExample { public static void main(String[] args) { ArrayList<Product> al = new ArrayList<>(); 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("现有产品列表:"); al.forEach(System.out::println); // 使用Stream API打印 Scanner sc = new Scanner(System.in); // --- Stream API 第一个元素的准确匹配 --- System.out.println("请输入要搜索的产品名称 (Stream 精确匹配,忽略大小写):"); String streamSearchExact = sc.nextLine(); Optional<Product> streamFoundExact = al.stream() .filter(p -> p.name.equalsIgnoreCase(streamSearchExact)) // 过滤匹配元素 .findFirst(); // 获取第一个匹配元素,返回Optional streamFoundExact.ifPresentOrElse( p -> System.out.println("Stream 找到准确匹配的产品: " + p), () -> System.out.println("Stream 未找到准确的匹配产品: " + streamSearchExact) ); // --- Stream API 模糊匹配所有元素 --- System.out.println("请输入要搜索的产品名称 (Stream 模糊匹配,忽略大小写):"); String streamSearchPartial = sc.nextLine(); List<Product> streamFoundPartial = al.stream() .filter(p -> p.name.toLowerCase().contains(streamSearchPartial.toLowerCase())) .collect(Collectors.toList()); // 在新列表中收集所有匹配元素 if (!streamFoundPartial.isEmpty()) { System.out.println("Stream 找到模糊匹配产品:"); streamFoundPartial.forEach(System.out::println); } else { System.out.println("Stream 未找到模糊匹配产品: " + streamSearchPartial); } sc.close(); } }

Stream API 优势:

  • 代码简洁性: 使用Lambda表达式和方法引用,代码更加紧凑,易于阅读。
  • 可读性: 链式调用使数据处理过程一目了然。
  • 并行处理: Stream API 可以很容易地切换到并行流(parallelStream()在处理大量数据时提高性能。

4. 性能考虑和最佳实践

在选择搜索方法时,性能也是一个重要的考虑因素,除了代码的简洁性。

  1. 选择合适的匹配方法:

    • 精确匹配(equals() / equalsIgnoreCase()):适用于需要完全匹配的场景。
    • 模糊匹配(contains()):适用于部分匹配或关键字搜索场景。
    • 在比较之前,始终考虑字符串的大小写敏感性,并根据需要选择equals()、equalsIgnoreCase()或先统一转换为小写/大写再比较。
    • 在访问对象属性时,应进行空值检查,以避免Nullpointerexception。例如:if (p.name != null && p.name.equalsIgnoreCase(searchName))。
  2. 数据结构选择与性能优化:

    • ArrayList的线性搜索: 无论是传统迭代还是Streamm API,根据属性在ArrayList中搜索的平均时间复杂度是OrrayList(N),也就是说,大约一半的元素需要遍历。这种性能通常可以接受小列表或不频繁搜索。
    • 快速搜索HashMap: 如果需要根据一个唯一的属性(如产品ID)、频繁快速地搜索唯一的产品名称,因此在Hashmap中存储数据将是一个更好的选择。Hashmap提供平均O(1)搜索时间复杂性。

    以下是如何使用Hashmap快速搜索的例子:

    import java.util.*; // 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 String toString() { return "Product{" + "id=" + id + ", name='" + name + '\'' + ", price=" + price + '}'; } } public class HashMapSearchExample { public static void main(String[] args) { ArrayList<Product> al = new ArrayList<>(); 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)); // 将 ArrayList 转换为 HashMap 快速搜索方便 // 键为产品名称(转换为小写支持不区分大小写搜索),值为产品对象 Map<String, Product> productMap = new HashMap<>(); for (Product p : al) { // 假设产品名称是唯一的,或者我们只关心第一个同名产品 productMap.put(p.name.toLowerCase(), p); } // 若产品名称不是唯一的,并且需要存储所有同名产品,则需要存储同名产品 Map<String, List<Product>> System.out.println("现有产品清单 (Hashmap显示):"); productMap.



http://www.jsqmd.com/news/543711/

相关文章:

  • Ryujinx开源项目:跨平台Switch游戏模拟解决方案
  • Win11Debloat系统优化工具:提升Windows效率的全面解决方案
  • vLLM-v0.17.1效果展示:vLLM 0.17.1对Long Context(256K)支持验证
  • OpenClaw定时任务:nanobot自动化日程管理
  • 电子系统接口设计与电路符号解析
  • LingBot-Depth效果展示:稀疏深度数据补全惊艳案例集
  • OpenClaw问题排查指南:GLM-4.7-Flash接口连接失败解决方案
  • Kubernetes 存储性能优化:从持久卷到存储类
  • Phi-4-Reasoning-Vision快速部署:Kubernetes双卡节点调度与资源预留配置
  • 创意伙伴 - OpenClaw在内容创作中的应用
  • 一文读懂:智能体身份权限治理演进实录
  • OpenClaw 一周实战总结:普通人的 AI 助理使用报告
  • 汉语到底比其他语言强在哪?
  • Wan2.2-I2V-A14B安全与权限管理:基于JWT的API访问控制设计
  • 谷歌 Lyria 3 Pro 正式发布,支持生成完整 3 分钟曲目
  • “Token”应该被翻译成什么?错了,你应该先搞清楚什么是“Token“
  • QtScrcpy快捷键深度定制指南:从效率痛点到操作自由
  • WuliArt Qwen-Image Turbo新手必看:Web界面操作,一键保存高清图片
  • 运维必看:你的uWSGI老版本还在线上跑?CVE-2018-7490目录穿越漏洞自查与修复指南
  • OpenCore全流程管理效率工具:OCAuxiliaryTools零基础入门指南
  • 京东抢购脚本终极指南:如何用JDspyder轻松抢到茅台等热门商品
  • 利用NLP-StructBERT构建学术论文查重与创新点分析系统
  • 计算机毕业设计:基于Python的美食数据分析评价预测系统 Django框架 LSTM Hadoop Spark Hive 可视化 大数据 食品 食物(建议收藏)✅
  • 在Ubuntu 20.04上搞定OpenFace:一份保姆级安装与避坑指南(含CEN模型和虚拟显示配置)
  • 紧急通知:2024年Q3起欧盟EDPS已将差分隐私实现纳入DPIA强制审查项——Python开发者必须立即核查的4个代码检查点
  • 深入解析RFC CO_XT_COMPONENT_ADD在生产订单组件添加中的高效应用
  • 零代码AI修图:LongCat镜像部署与使用完整指南
  • 【技术解析】从模型到策略:离心式作动器在车辆横向振动抑制中的闭环控制设计
  • 在构建高并发、海量数据的分布式系统时,数据存储与治理是核心挑战。单机数据库的性能瓶颈、ID 冲突、历史数据膨胀等问题,都需要通过架构层面的设计来解决
  • 别急着跑流程!单细胞测序数据分析前,你的GEO数据真的‘干净’吗?