筛选ArrayList元素至新集合:两种方案优劣对比及优化建议
方案分析与优化建议
嘿,我来帮你拆解这两个方案的差异,再聊聊更合适的实现思路~
首先得先明确你的核心需求:你是要完全匹配invoice_no和invNumber完全相等,还是要包含匹配invoice_no中包含invNumber作为子串?这两个方案的逻辑本质是不一样的,先对齐需求再谈优劣:
1. 现有两个方案的差异与性能对比
方案一(equals完全匹配):
for (InvoiceSubData s : invProperty) { if (invNumber.equals(s.getInvoiceNo())) { newProperty.add(s); } }这个是严格匹配整个
invoice_no字符串,逻辑精准(如果你的需求就是找完全相等的记录)。性能上,equals方法会先比较字符串长度,再逐字符匹配,一旦发现不匹配就终止,效率比子串查找高很多。方案二(contains包含匹配):
for (InvoiceSubData s : invProperty) { if (s.getInvoiceNo().contains(invNumber)) { newProperty.add(s); } }这个是检查
invoice_no是否包含invNumber作为子串,逻辑和方案一完全不同(比如invNumber是"INV123",那invoice_no是"INV123-001"也会被匹配)。性能上,contains需要做子串查找,开销比equals大,尤其是当字符串较长时差异更明显。
所以如果需求是完全匹配,方案一才是正确且更优的;如果是包含匹配,那方案二符合需求,但性能不如完全匹配场景。
2. 更简洁高效的替代方案(Java 8+)
如果你用的是Java 8及以上版本,推荐用Stream API实现,代码更简洁易读,性能和循环方式持平(JVM甚至会做底层优化):
完全匹配场景:
List<InvoiceSubData> newProperty = invProperty.stream() .filter(invoice -> invNumber.equals(invoice.getInvoiceNo())) .collect(Collectors.toList());
包含匹配场景:
List<InvoiceSubData> newProperty = invProperty.stream() .filter(invoice -> invoice.getInvoiceNo().contains(invNumber)) .collect(Collectors.toList());
另外,如果你需要频繁根据invoice_no查询,可以提前把invProperty按invoice_no分组存入Map,后续查询直接取值,时间复杂度降到O(1):
// 仅需执行一次的分组操作 Map<String, List<InvoiceSubData>> invoiceGroupMap = invProperty.stream() .collect(Collectors.groupingBy(InvoiceSubData::getInvoiceNo)); // 后续查询直接获取对应列表 List<InvoiceSubData> newProperty = invoiceGroupMap.getOrDefault(invNumber, new ArrayList<>());
这个方式适合多次查询的场景,一次性分组的开销会被多次查询抵消,整体效率更高。
总结
- 单次查询+完全匹配:方案一或Stream版本都可,Stream更简洁
- 单次查询+包含匹配:方案二或对应Stream版本
- 多次查询:提前分组到Map是最优解
内容的提问来源于stack exchange,提问作者D.Madu
相关产品推荐
相关产品推荐

