如何更高效地从ArrayList生成带计数功能的HashMap?
优化街区房源统计的实现方式
你的思路是对的,但确实有更简洁、高效的实现方式,还能去掉冗余代码。咱们一步步拆解优化:
第一步:移除冗余的空判断
原代码里的if (housesInNbrhood.isEmpty())完全没必要——当Map为空时,containsKey自然会返回false,直接走到最后的else分支执行put。去掉这个判断后,代码已经清爽很多:
public HashMap<String, Integer> sortHousesInNbrhood(ArrayList<AirbnbListing> priceRangeListing) { HashMap<String, Integer> housesInNbrhood = new HashMap<>(); for (AirbnbListing listing : priceRangeListing) { String neighbourhood = listing.getNeighbourhood(); if (housesInNbrhood.containsKey(neighbourhood)) { housesInNbrhood.replace(neighbourhood, housesInNbrhood.get(neighbourhood) + 1); } else { housesInNbrhood.put(neighbourhood, 1); } } return housesInNbrhood; }
第二步:用HashMap.merge()简化逻辑
Java 8+给HashMap加了merge方法,专门解决这种「键存在则累加,不存在则初始化」的场景。一行代码就能替代原来的if-else,还避免了重复的get和containsKey调用:
public HashMap<String, Integer> sortHousesInNbrhood(ArrayList<AirbnbListing> priceRangeListing) { HashMap<String, Integer> housesInNbrhood = new HashMap<>(); for (AirbnbListing listing : priceRangeListing) { // 三个参数:要插入的键、初始值、存在时的合并逻辑(这里是累加) housesInNbrhood.merge(listing.getNeighbourhood(), 1, Integer::sum); } return housesInNbrhood; }
merge方法的优势在于:内部会高效处理键的存在性检查,代码更紧凑,可读性也更强。
第三步:用Stream API实现声明式编程
如果你的项目已经用上Java 8及以上,完全可以用Stream API写出更简洁的声明式代码,彻底告别手动循环:
public Map<String, Integer> sortHousesInNbrhood(ArrayList<AirbnbListing> priceRangeListing) { return priceRangeListing.stream() .collect(Collectors.groupingBy( AirbnbListing::getNeighbourhood, // 按街区分组 HashMap::new, // 指定返回HashMap类型(如果需要的话) Collectors.summingInt(listing -> 1) // 统计每组的元素数量 )); }
如果不需要强制返回HashMap(返回Map接口更灵活),还可以简化成:
public Map<String, Integer> sortHousesInNbrhood(ArrayList<AirbnbListing> priceRangeListing) { return priceRangeListing.stream() .collect(Collectors.groupingBy( AirbnbListing::getNeighbourhood, Collectors.summingInt(listing -> 1) )); }
这种方式更符合现代Java的编程风格,代码意图一目了然——「把房源按街区分组,统计每组的数量」。
内容的提问来源于stack exchange,提问作者Logi Gunaratnam
相关产品推荐
相关产品推荐

