做网站要不要花钱做店长,杭州p2p网站开发商,wordpress页面文件目录,网站空间源码HashMap 基本介绍
HashMap 是 Java 中的一个集合类#xff0c;实现了 Map 接口#xff0c;用于存储键值对#xff08;key-value#xff09;数据。它基于哈希表的数据结构实现#xff0c;可以实现高效的查找、插入和删除操作。
HashMap 细节讨论
无序性#xff1a; Has…HashMap 基本介绍
HashMap 是 Java 中的一个集合类实现了 Map 接口用于存储键值对key-value数据。它基于哈希表的数据结构实现可以实现高效的查找、插入和删除操作。
HashMap 细节讨论
无序性 HashMap 中的元素是无序的即遍历的顺序不一定是元素插入的顺序。键唯一性 HashMap 的键是唯一的不允许重复的键。如果插入相同的键后面的值会覆盖前面的值。允许 null 键和 null 值 HashMap 允许使用 null 作为键并且允许键对应的值为 null但是只允许有一个null键因为键是唯一的。非线程安全 HashMap 不是线程安全的如果多个线程同时访问并修改同一个 HashMap可能会导致数据不一致或其他错误。初始容量和负载因子 HashMap 允许设置初始容量和负载因子初始容量是哈希表中桶的数量负载因子是哈希表在达到多满时进行扩容操作(这里和HashSet一样因为HashSet的底层是用HashMap实现的)。
使用注意事项
线程安全性 如果需要在多线程环境中使用 HashMap需要进行适当的同步处理或者考虑使用线程安全的集合类如 ConcurrentHashMap。哈希冲突 当不同的键映射到相同的哈希值时发生哈希冲突。HashMap 使用链表JDK8 之前或红黑树JDK8 及以后来处理哈希冲突。equals 和 hashCode 方法 在使用自定义类作为 HashMap 的键时需要正确实现该类的 equals 和 hashCode 方法以确保键的唯一性和正确的哈希计算。
常用方法
以下是一些常用的 HashMap 方法
put(key, value): 向 HashMap 中插入键值对。get(key): 根据键获取对应的值。containsKey(key): 判断是否包含指定键。containsValue(value): 判断是否包含指定值。remove(key): 根据键删除对应的键值对。size(): 返回 HashMap 中键值对的数量。isEmpty(): 判断 HashMap 是否为空。keySet(): 返回包含所有键的集合。values(): 返回包含所有值的集合。entrySet(): 返回包含所有键值对的集合。
底层源码和底层实现
HashMap 的底层实现主要是基于哈希表其中每个桶bucket是一个链表或红黑树。当哈希冲突发生时新的键值对会被插入到相应的桶中。
HashMap 的底层源码非常复杂涉及哈希计算、扩容、桶的处理等多个方面。如果想深入了解 HashMap 的底层实现可以查阅 Java 的源代码或相关的学习资料。 HashMap的遍历代码
public class HashMap_ {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put(1,new Student(1,ret1,23,计算机));hashMap.put(2,new Student(2,ret2,23,计算机));hashMap.put(3,new Student(3,ret3,23,计算机));System.out.println(hashMap);for (Object entry : hashMap.entrySet()) {Map.Entry entry1 (Map.Entry) entry;System.out.println(entry1.getKey() entry1.getValue());}Set set hashMap.keySet();for (Object key :set) {System.out.println(key hashMap.get(key));}}
}class Student{private String sno;private String name;private int age;private String major;public Student(String sno, String name, int age, String major) {this.sno sno;this.name name;this.age age;this.major major;}public String getSno() {return sno;}public void setSno(String sno) {this.sno sno;}public String getName() {return name;}public void setName(String name) {this.name name;}public int getAge() {return age;}public void setAge(int age) {this.age age;}public String getMajor() {return major;}public void setMajor(String major) {this.major major;}Overridepublic boolean equals(Object o) {if (this o) return true;if (o null || getClass() ! o.getClass()) return false;Student student (Student) o;return age student.age Objects.equals(sno, student.sno) Objects.equals(name, student.name) Objects.equals(major, student.major);}Overridepublic int hashCode() {return Objects.hash(sno, name, age, major);}Overridepublic String toString() {return Student{ sno sno \ , name name \ , age age , major major \ };}
}HashMap的底层代码
/*HashMap底层原理1. 执行构造器 new HashMap()初始化加载因子 loadFactor 0.75HashMap$Node[] table null2. 执行 put 调用 hash 方法计算 key 的 hash 值(h key.hashCode()) ^ (h 16)public V put (K key, V value){//K java value 10return putVal(hash(key), key, value, false, true);}3. 执行 putValfinal V putVal ( int hash, K key, V value,boolean onlyIfAbsent, boolean evict){NodeK, V[] tab;NodeK, V p;int n, i;//辅助变量//如果底层的 table 数组为 null, 或者 length 0 , 就扩容到 16if ((tab table) null || (n tab.length) 0)n (tab resize()).length;//取出 hash 值对应的 table 的索引位置的 Node, 如果为 null, 就直接把加入的 k-v创建成一个 Node ,加入该位置即可if ((p tab[i (n - 1) hash]) null)tab[i] newNode(hash, key, value, null);else {NodeK, V e;K k;//辅助变量// 如果 table 的索引位置的 key 的 hash 相同和新的 key 的 hash 值相同// 并满足(table 现有的结点的 key 和准备添加的 key 是同一个对象 || equals 返回真)就认为不能加入新的 k-vif (p.hash hash ((k p.key) key || (key ! null key.equals(k))))e p;else if (p instanceof TreeNode)//如果当前的 table 的已有的 Node 是红黑树就按照红黑树的方式处理e ((TreeNodeK, V) p).putTreeVal(this, tab, hash, key, value);else {//如果找到的结点后面是链表就循环比较for (int binCount 0; ; binCount) {//死循环if ((e p.next) null) {//如果整个链表没有和他相同,就加到该链表的最后p.next newNode(hash, key, value, null);//加入后判断当前链表的个数是否已经到 8 个到 8 个后//就调用 treeifyBin 方法进行红黑树的转换if (binCount TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash hash //如果在循环比较过程中发现有相同,就 break,就只是替换 value((k e.key) key || (key ! null key.equals(k))))break;p e;}}if (e ! null) { // existing mapping for keyV oldValue e.value;if (!onlyIfAbsent || oldValue null)e.value value; //替换key 对应 valueafterNodeAccess(e);return oldValue;}}modCount;//每增加一个 Node ,就 sizeif (size threshold[12 - 24 - 48])//如 size 临界值就扩容resize();afterNodeInsertion(evict);return null;}5. 关于树化(转成红黑树)//如果 table 为 null ,或者大小还没有到 64暂时不树化而是进行扩容. //否则才会真正的树化 - 剪枝final void treeifyBin (Node K, V []tab,int hash){int n, index;NodeK, V e;if (tab null || (n tab.length) MIN_TREEIFY_CAPACITY)resize();}*/