一、HashMap原理
HashMap是基于哈希表的实现,它是一种将键映射到值的数据结构。
HashMap可以通过key来访问value,因此它提供了非常快速的(近似常数时间)查询操作。
HashMap采用数组、链表、红黑树结合的方式实现,数组被分为一个一个的桶,每个桶里面存放一条链表或者红黑树,当链表长度超过8,并且数组长度大于64时,链表就会转化为红黑树,这样可以提高查询效率。
二、HashMap和Map区别简答
Map是所有映射类型的基类,HashMap是Map接口的一种实现。
因此,HashMap继承了Map接口的所有属性和行为。在Java中,Map和HashMap都是非常常见的用于存储键值对的容器。
Map是一个映射接口,它提供了每个键都可以对应一个值的存储机制。HashMap是通过继承AbstractMap来实现的,而且它是一种基于哈希表的Map实现。
三、HashMap方法
HashMap提供了以下方法:
1. put(K key, V value):将指定的值与此映射中的指定键相关联。
2. get(Object key):返回此映射中指定键所映射的值。
3. remove(Object key):从此映射中移除指定键的映射。
4. containsKey(Object key):如果此映射包含指定键的映射,则返回true。
5. containsValue(Object value):如果此映射将一个或多个键映射到指定值,则返回true。
6. keySet():返回此映射中包含的键的Set视图。
7. values():返回此映射中包含的值的Collection视图。
8. entrySet():返回此映射中包含的映射的Set视图。
四、HashMap的理解
HashMap是一个用于存储键值对的数据结构,它提供了五种不同的存储方式:数组、链表、红黑树、字段元素、桶容量因子。其中,数组、链表和红黑树的实现来自于Java集合框架的LinkedList和TreeMap类,字段元素和桶容量因子则是HashMap独有的特性。
作为HashMap使用者,我们不需要了解HashMap内部的实现原理,只需要了解其提供的方法即可。但是如果想要深入了解Java集合框架,建议可以学习一下HashMap的源码实现。
五、HashMap的get方法
get方法是HashMap中最常用的方法之一,它用于返回与指定键相关联的值。在HashMap中,get方法可以通过以下步骤来完成:
1. 将key的hashCode作为参数入参传递给hash方法。
public V get(Object key) { Nodee; return (e = getNode(hash(key), key)) == null ? null : e.value; }
2. hash方法会将hashCode的高位异或低位,来保证一个更好的hash值分布,得到对应的桶的索引。
final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
3. 根据桶的索引定位到对应的桶,遍历桶中的链表,如果key相同,则返回对应的value。
final NodegetNode(int hash, Object key) { Node [] tab; Node first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode )first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }
六、HashMap用法
HashMap用法非常广泛,可以通过创建HashMap对象,调用其提供的put方法,向HashMap中添加键值对:
HashMapmap = new HashMap<>(); map.put("apple", 1); map.put("banana", 2); map.put("orange", 3);
也可以通过get方法,从HashMap中获取指定键对应的值:
Integer value = map.get("apple");
七、HashMap集合说法正确的是
HashMap是一种无序的集合,它不保证集合中元素的顺序。
另外,HashMap中可以存储null值和null键。
八、HashMap集
HashMap是一种key-value的数据结构。
它的内部是通过哈希表的方式来存储数据的。
HashMap中的key和value都可以为null。
当HashMap中出现hash冲突的时候,会采用链表的方式来存储。
九、HashMap扩容
HashMap在存储元素的时候,存在一个负载因子(load factor)的概念。
当元素的数量达到负载因子与容量的乘积时,HashMap就会自动扩容。默认的负载因子是0.75,即当HashMap的元素数量达到容量的75%时,就会进行扩容。
在扩容的时候,HashMap会将元素重新分配到新的数组中。这个过程需要对每个元素重新计算hash值,因此效率较低。
十、HashMap源码选取
在HashMap中,我们可以看一下Node类的定义:
static class Node<K,V> implements Map.Entry<K,V> { final int hash; final K key; V value; Node<K,V> next; Node(int hash, K key, V value, Node<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } public final K getKey() { return key; } public final V getValue() { return value; } public final String toString() { return key + "=" + value; } public final int hashCode() { return Objects.hashCode(key) ^ Objects.hashCode(value); } public final V setValue(V newValue) { V oldValue = value; value = newValue; return oldValue; } public final boolean equals(Object o) { if (o == this) return true; if (o instanceof Map.Entry) { Map.Entry e = (Map.Entry)o; if (Objects.equals(key, e.getKey()) && Objects.equals(value, e.getValue())) return true; } return false; } }
Node类用于存储键值对,也就是哈希表中的元素。它包含了hashCode、key、value、next四个字段,其中hashCode是计算得到的键的哈希值,key和value分别对应键和值,next是指向下一个元素的指针。