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

Java集合框架实战:HashMap与HashSet的5个高频使用场景解析

Java集合框架实战:HashMap与HashSet的5个高频使用场景解析

在Java开发中,集合框架是每个开发者必须掌握的核心技能之一。HashMap和HashSet作为最常用的集合类,它们的高效性和灵活性使其在各种业务场景中大放异彩。本文将深入解析5个实际开发中的高频使用场景,帮助开发者更好地理解如何根据业务需求选择合适的集合类。

1. 电商购物车中的商品去重

电商平台的购物车功能是HashSet最典型的应用场景之一。当用户多次添加同一商品时,系统需要自动合并数量而非重复显示,这正是HashSet的用武之地。

public class ShoppingCart { private Set<Product> items = new HashSet<>(); public void addItem(Product product) { if (items.contains(product)) { // 商品已存在,更新数量逻辑 } else { items.add(product); } } }

实现要点

  • 自定义Product类必须正确重写equals()hashCode()方法
  • HashSet的contains操作时间复杂度为O(1),远优于List的O(n)
  • 实际业务中常结合Map存储商品数量信息

提示:在重写hashCode()时,应确保相同对象的hashCode相同,不同对象尽量有不同的hashCode

2. 用户权限校验中的快速查找

权限系统需要频繁判断用户是否拥有特定权限,HashMap的快速查找特性使其成为理想选择。

public class PermissionService { private Map<String, Permission> permissionMap = new HashMap<>(); public boolean hasPermission(String permissionKey) { return permissionMap.containsKey(permissionKey); } public void loadPermissions(List<Permission> permissions) { for (Permission p : permissions) { permissionMap.put(p.getKey(), p); } } }

性能对比表:

数据结构插入时间复杂度查询时间复杂度内存占用
ListO(1)O(n)
HashMapO(1)O(1)较高
TreeMapO(log n)O(log n)

3. 数据统计与词频分析

文本处理中统计词频是HashMap的经典应用,下面是一个完整的实现示例:

public class WordCounter { public Map<String, Integer> countWords(String text) { Map<String, Integer> frequencyMap = new HashMap<>(); String[] words = text.split("\\s+"); for (String word : words) { word = word.toLowerCase().replaceAll("[^a-z]", ""); frequencyMap.merge(word, 1, Integer::sum); } return frequencyMap; } }

优化技巧

  • 使用merge()方法简化计数逻辑
  • 预处理文本提高统计准确性
  • 对于大数据量,考虑使用ConcurrentHashMap

4. 轻量级缓存实现

HashMap常被用于实现简单的内存缓存,下面是一个带过期机制的缓存实现:

public class SimpleCache<K, V> { private Map<K, CacheEntry<V>> cache = new HashMap<>(); private long defaultExpiry = 60_000; // 默认1分钟 public void put(K key, V value) { put(key, value, defaultExpiry); } public void put(K key, V value, long expiry) { cache.put(key, new CacheEntry<>(value, System.currentTimeMillis() + expiry)); } public V get(K key) { CacheEntry<V> entry = cache.get(key); if (entry == null || entry.isExpired()) { cache.remove(key); return null; } return entry.getValue(); } private static class CacheEntry<V> { private V value; private long expiryTime; // 构造方法和getter省略 boolean isExpired() { return System.currentTimeMillis() > expiryTime; } } }

5. 数据库结果集处理

在处理数据库查询结果时,HashMap可用于建立对象间的映射关系:

public class UserRepository { public Map<Long, User> getUserMap() { List<User> users = jdbcTemplate.query("SELECT * FROM users", this::mapRow); return users.stream().collect(Collectors.toMap(User::getId, Function.identity())); } private User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getLong("id")); user.setName(rs.getString("name")); return user; } }

高级应用

  • 多级映射:Map<DepartmentId, Map<UserId, User>>
  • 索引加速:为常用查询字段建立额外映射
  • 结果集转换:将行数据转为领域对象

底层原理与性能优化

理解HashMap的工作原理对正确使用至关重要。当元素数量超过阈值(容量*负载因子)时,HashMap会进行扩容:

// 初始化一个预计存放100个元素的HashMap int expectedSize = 100; float loadFactor = 0.75f; int initialCapacity = (int) (expectedSize / loadFactor) + 1; Map<String, String> map = new HashMap<>(initialCapacity, loadFactor);

扩容过程

  1. 创建新的Entry数组(通常为原大小的2倍)
  2. 重新计算所有元素的存储位置
  3. 将元素转移到新数组中

注意:频繁扩容会影响性能,初始化时应合理预估大小

HashSet的去重原理依赖于HashMap的键唯一性。当向HashSet添加元素时:

// HashSet的add方法实际实现 public boolean add(E e) { return map.put(e, PRESENT) == null; }

其中PRESENT是一个固定的虚拟值,所有元素共享。这种实现使得HashSet的所有操作实际上都是委托给HashMap完成的。

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

相关文章:

  • Dify+Docker镜像加速实战:3步搞定国内网络环境下的Windows部署
  • 2026年03月国内那些评价好的异型钢厂家分析,有实力的异型钢优质企业盘点及核心优势详细解读 - 品牌推荐师
  • 2026年AI率从39%降到0%的完整操作步骤,一步步教你 - 还在做实验的师兄
  • Cruise和Simulink联合仿真,纯电动汽车动力经济性仿真EV模型, 内容包括
  • 用Scapy玩转网络探测:从Ping扫描到SYN半开扫描的实战指南
  • Stable Yogi Leather-Dress-Collection 模型 API 封装与运维部署实战
  • 密码学算法 - Miller-Rabin 素数检验
  • 旧手机变废为宝:用KSWeb搭建个人网站服务器的完整指南(含内网穿透教程)
  • 2026年公众号降AI率怎么操作?自媒体人亲测这招管用 - 还在做实验的师兄
  • 避开VisionPro坐标空间三大坑:命名冲突、像素空间误解与转换API正确用法
  • 2026年降AI工具TOP5盘点,从性价比到效果一次看明白 - 还在做实验的师兄
  • IPsec协议考古学:从RFC文档到Wireshark抓包的时空对话
  • HY-Motion 1.0效果展示:标准版vs Lite版在关节旋转精度上的对比分析
  • 通义千问3-Reranker-0.6B实操手册:batch_size调优与内存占用平衡策略
  • 废旧安卓手机秒变Web服务器:KSWeb+Termux+Ngrok保姆级配置指南(含免费隧道申请)
  • Ostrakon-VL-8B实战:基于YOLOv11的目标检测与视觉理解融合应用
  • Pixel Dimension Fissioner一文详解:16-bit冒险工坊交互设计与技术实现
  • Qwen3-32B-Chat百度技术趋势研判:2025年大模型私有部署的硬件选型指南
  • AI研发团队必看:BAAI/bge-m3语义引擎集成最佳实践
  • Windows下用Hashcat+GPU暴力破解Excel密码:从提取Hash到实战破解全流程
  • Whisky技术解析:macOS上的Windows兼容层创新方案
  • IDEA插件搬家指南:用ToolBox升级后如何手动迁移插件配置(附2023版路径大全)
  • Pixel Dimension Fissioner效果展示:同一产品功能点裂变为Figma提示词+PRD描述+海报文案
  • YOLO12行业落地:半导体晶圆厂中wafer载具、探针卡与缺陷区域定位
  • 考虑特性分布的储能电站接入的电网多时间尺度源储荷协调调度策略附Matlab代码
  • Simple Automatic Resource Synchronization Method for Vulkan Applications
  • 树莓派安全远程访问:除了改密码,用Cpolar做内网穿透还要注意这几点
  • Pixel Dimension Fissioner效果展示:裂变结果支持按‘创意强度’‘专业度’‘亲和力’三维排序
  • LobeChat模型切换指南:如何在Qwen-8B等模型间自由切换
  • SAM 3开源模型实战:构建私有化图像标注平台,替代LabelMe效率提升5倍