求优化:获取ArrayList中包含唯一文本的WebElement的索引的优雅实现方案
更简洁优雅的解决方案
当然可以!你的现有代码确实能实现需求,但我们可以利用Java Stream API的特性,用更紧凑、高效的方式完成这个任务,同时避免创建多余的中间集合。
方案一:一次遍历完成(推荐)
这个方案通过IntStream遍历索引,配合HashSet的特性,一次遍历就能筛选出每个唯一文本第一次出现的索引:
ArrayList<WebElement> webElementsWithText = getWebElements(); Set<String> seenTexts = new HashSet<>(); List<Integer> uniqueIndices = IntStream.range(0, webElementsWithText.size()) // 利用HashSet.add()的返回值:文本未见过则添加并返回true,否则返回false .filter(i -> seenTexts.add(webElementsWithText.get(i).getText())) .boxed() // 将int转换为Integer .collect(Collectors.toList());
为什么这个方案更好?
- 效率更高:只需要遍历一次元素集合,不需要先提取所有文本、再去重、再循环找索引这三步操作
- 内存更友好:减少了两个中间
ArrayList的创建,降低内存开销 - 逻辑连贯:从索引遍历到筛选再到收集,整个流程一气呵成,可读性强
方案二:利用分组保留插入顺序
如果你需要严格保持原集合中唯一文本的出现顺序(和原代码中distinct()的行为一致),也可以用Collectors.toMap结合LinkedHashMap来实现:
ArrayList<WebElement> webElementsWithText = getWebElements(); List<Integer> uniqueIndices = IntStream.range(0, webElementsWithText.size()) .boxed() .collect(Collectors.toMap( // 键:元素的文本内容 i -> webElementsWithText.get(i).getText(), // 值:元素的索引 Function.identity(), // 遇到重复文本时,保留第一次出现的索引 (existingIndex, newIndex) -> existingIndex, // 用LinkedHashMap保证顺序和原集合中第一次出现的顺序一致 LinkedHashMap::new )) .values() .stream() .collect(Collectors.toList());
这个方案的优势是直观体现了“按文本分组,取每组第一个索引”的逻辑,同时通过LinkedHashMap保证结果顺序和原集合一致。
对比原代码的优化点
原代码需要三次遍历(提取文本、去重、循环找索引),而上面的两种方案都只需要一次或两次遍历,同时减少了中间数据结构的使用,代码更简洁也更高效。
内容的提问来源于stack exchange,提问作者andris93
相关产品推荐
相关产品推荐

