Java中ArrayList多条件叠加过滤结果异常的解决方案问询
问题根因
你的过滤逻辑存在两个核心错误,导致多条件无法叠加生效:
- 多关键词匹配逻辑错误:你在遍历每个Chip时,每次都从**原始全量列表
arrayULD**重新筛选,且单轮筛选只校验当前Chip的关键词,最终得到的是所有关键词匹配结果的并集,而非多条件同时满足的交集。另外代码中arrayFiltered;存在多余分号的语法问题,contains(uld)的去重逻辑完全多余——遍历原始列表时每个条目只会被判断一次,不存在重复添加的可能。 - 过滤规则没有统一串联:你把字符串关键词过滤、
withNet布尔属性过滤拆成了两个独立逻辑,每次执行单条过滤规则时都从原始列表重新生成结果,没有把多个规则同时作用在同一条数据上做校验,自然无法实现条件叠加。另外withNet过滤返回全量通常是调用方法时传入的布尔值和开关状态绑定反了,或者过滤逻辑没有和关键词规则合并执行。
正确实现方案
核心原则:每次任意过滤条件变更时,都从不变的原始全量数据出发,对每条数据依次校验所有生效的过滤规则,所有规则全部满足的条目才加入结果集。不要在上一次的过滤结果上叠加筛选(容易受历史结果状态影响),也不要每个规则单独从原始列表筛选后合并(会变成结果并集)。
首先在类中定义一个成员变量存储永远不修改的原始全量数据:
// 初始化时存入全量数据,后续过滤永远从这个列表取源数据,不要修改它的内容 private List<ItemULD> originalUldList = new ArrayList<>();
所有会触发过滤的操作(文本框输入回车生成Chip、Chip删除/选中状态变化、withNet过滤开关点击),都统一调用下面的过滤方法得到结果:
/** * 统一过滤方法 * @param checkedChipIds 当前ChipGroup中所有选中/生效的Chip ID * @param needFilterWithNet 是否开启带网兜过滤,true=只返回withNet=true的条目,false=不校验该属性 * @return 过滤后的结果列表 */ private List<ItemULD> getFilteredResult(List<Integer> checkedChipIds, boolean needFilterWithNet) { List<ItemULD> result = new ArrayList<>(); // 提前收集所有需要匹配的关键词,避免循环条目时重复findView List<String> matchKeywords = new ArrayList<>(); for (Integer chipId : checkedChipIds) { Chip chip = grupoChip.findViewById(chipId); if (chip != null && chip.getText() != null) { String keyword = chip.getText().toString().trim(); if (!keyword.isEmpty()) { // 空关键词直接跳过,避免contains("")匹配所有条目 matchKeywords.add(keyword); } } } // 遍历全量原始数据,逐条校验规则 for (ItemULD uld : originalUldList) { // 校验规则1:withNet属性 boolean netMatch = !needFilterWithNet || uld.iswithNet(); if (!netMatch) { continue; } // 校验规则2:所有关键词必须同时命中(如果需要任意关键词命中即可,可调整下方判断逻辑) boolean allKeywordMatch = true; String numUldStr = String.valueOf(uld.getNumULD()); String contourStr = uld.getContour(); for (String keyword : matchKeywords) { boolean singleKeywordHit = numUldStr.contains(keyword) || contourStr.contains(keyword); if (!singleKeywordHit) { allKeywordMatch = false; break; } } // 所有规则都满足,加入结果集 if (allKeywordMatch) { result.add(uld); } } return result; }
效果验证
用你提供的测试数据验证:
- 输入关键词
123时,id1(num包含123)、id3(num包含123)命中,返回2条,和你之前的正确结果一致。 - 再添加关键词
AF时,id1的contour是EK不命中AF,id2的num是652466不命中123,只有id3同时满足contour=AF、num包含123,返回1条,符合预期。 - 开启
withNet过滤时,只有id1的withNet为1,会单独返回id1;如果同时和关键词组合,会在匹配关键词的基础上再校验withNet属性,不会出现返回全量的问题。
注意事项
- 不要把过滤后的结果赋值给
originalUldList,必须保证这个列表永远是初始化时的全量数据,否则多次过滤后源数据会越来越少。 - 如果你的业务需求是「任意一个关键词命中就算匹配」,只需要把关键词校验逻辑改成:只要有一个关键词命中,就标记
allKeywordMatch = true并break循环即可。 - 建议给
ItemULD类的属性匹配标准JavaBean命名规范,比如isWithNet()、getNumUld(),避免反射或者框架调用时出现找不到方法的问题。
内容的提问来源于stack exchange,提问作者Dúver Cruz
相关产品推荐
相关产品推荐

