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

手撕 简易HashMap

put()、get()、remove() 方法

计算存储数组位置和k-vNode节点

    public int indexOf(K key){return key.hashCode() & (table.length - 1);}static class Node<K, V>{K key;V value;Node<K, V> next;public Node(K key, V value){this.key = key;this.value = value;}}
  • put(K key,V value)

向 HashMap 里存入数据的方法,逻辑是,先通过 hashCode() 方法获取 key 的 hash值,然后通过( n - 1) & hash 来得到该键值对存储在数据上的位置。

假如插入的位置没有数据,则直接插入,如果有数据,判断其key是否相同,如果相同就覆盖掉,如果不相同,就遍历这个“哈希桶”中的链表,将其 k-v 以链表的方式插入链表的尾部。

public V put(K key, V value){int keyIndex = indexOf(key);Node<K, V> head = table[keyIndex];if(head == null){table[keyIndex] = new Node<>(key, value);size++;resizeIfNecessary();return null;}while(true){if(head.key.equals(key)){V oldValue = head.value;head.value = value;return oldValue;}if(head.next == null){head.next = new Node<>(key, value);size++;resizeIfNecessary();return null;}head = head.next;}}
  • get(K key)

获取 HashMap 里数据的方法,逻辑是,先通过 hashCode() 方法获取 key 的 hash值,然后通过( n - 1) & hash 来得到该键值对存储在数据上的位置。

假如该位置有数据并且与key相等,说明找到了直接返回,反之则遍历链表,没找到返回null。

    public V get(K key){int keyIndex = indexOf(key);Node<K, V> head = table[keyIndex];while(head != null){if(head.key.equals(key)){return head.value;}head = head.next;}return null;}
  • remove(K key)

删除 HashMap 里数据的方法,逻辑是,先通过 hashCode() 方法获取 key 的 hash值,然后通过( n - 1) & hash 来得到该键值对存储在数据上的位置。

假如为null,说明没有返回null,如果在数组上则直接删除,并将下一个节点放在数组位置上,若数组没有则需遍历链表寻找。注意在删除后需 “接上链表” 。

 public V remove(K key){int keyIndex = indexOf(key);Node<K, V> head = table[keyIndex];if(head == null){return null;}if(head.key.equals(key)){table[keyIndex] = head.next;size--;return head.value;}Node<K, V> pre = head;Node<K, V> current = head.next;while(current != null){if(current.key.equals(key)){pre.next = current.next;size--;return current.value;}pre = pre.next;current = current.next;}return null;}

扩容机制

负载因子为 0.75,也就是说当容量为 16 时,16 * 0.75 = 12 ,当存储第 13 个数据时,触发扩容机制。

扩容为原来数组的 2 倍。

遍历 HashMap 上的所有 k-v ,然后放在新的数组上。

 private void resizeIfNecessary(){if(this.size < table.length * 0.75){return;}Node<K, V>[] newTable = new Node[table.length * 2];for(Node<K, V> head : this.table){if(head == null){continue;}Node<K, V> current = head;while(current != null){int newIndex = current.key.hashCode() & (newTable.length - 1);if(newTable[newIndex] == null){newTable[newIndex] = current;Node<K, V> next = current.next;current.next = null;current = next;} else {Node<K, V> next = current.next;current.next = newTable[newIndex];newTable[newIndex] = current;current = next;}}}this.table = newTable;}

http://www.xdnf.cn/news/31591.html

相关文章:

  • YOLO11改进-Backbone-使用MobileMamba替换YOLO backbone 提高检测精度
  • 在服务器上部署MinIO Server
  • JMeter实现UI自动化测试的完整方案
  • 配置管理与系统文档
  • MyImgConverter:图片批量处理工具
  • 智能提示语全周期优化系统:云原生架构设计与工程实践
  • LPDDR中读操作不存在Additive Latency(AL)的技术思考
  • opencv 最近邻插值法的原理
  • 集合框架(详解)
  • 手机投屏到电视方法
  • 从UDS协议学习ISO网络七层架构:汽车诊断网络协议的分层逻辑剖析
  • vue3专题1------父组件中更改子组件的属性
  • 应急响应篇近源攻击Docker镜像容器分析Dockfile路径定位基线扫描
  • MPTCP 的吞吐困局
  • 数据库基础-B+树
  • 使用 #pragma warning(push) 局部开启更高等级
  • 性能比拼: Elixir vs Go
  • MATLAB 控制系统设计与仿真 - 39
  • 春和景明-C语言简单代码
  • 又一张支付牌照注销
  • 实现窗口函数
  • Python+Selenium+Pytest+POM自动化测试框架封装(完整版)
  • M|触碰你
  • HTML+CSS+JS(1)
  • 深度学习数据预处理:Dataset类的全面解析与实战指南
  • 基于机器学习 LSTM 算法的豆瓣评论情感分析系统
  • 方法引用和构造器引用
  • vulnhub靶场之【hacker-kid】靶机
  • 洛谷 P2606 [ZJOI2010] 排列计数
  • 第六周作业