HashMap是键值对的数据结构,存储的时候使用的是散列式存储。
java.util.HashMap的实现是一个标准的hash表+链表结构。
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
public abstract class AbstractMap<K, V> implements java.util.Map<K,V> {
/**
*
* @param the type of keys maintained by this map
* @param the type of mapped values
*
* @author Josh Bloch
* @see HashMap
* @see TreeMap
* @see Hashtable
* @see SortedMap
* @see Collection
* @see Set
* @since 1.2
*/
public interface Map<K, V> {}
Set<K> keySet();
Collection<V> values();
可以从源码里看到,根因是HashMap的key是Set数据结构,值是Collection的。
HashMap对象的key、value值均可为null。
HahTable对象的key、value值均不可为null。
且两者的的key值均不能重复,若添加key相同的键值对,后面的value会自动覆盖前面的value,但不会报错。
理论上是只要内存没有溢出是可以无限存储的,但是通过源码可以发现,最多存储Integer.MAX_VALUE
这么多。
/**
* Returns the number of key-value mappings in this map. If the
* map contains more than {@code Integer.MAX_VALUE} elements, returns
* {@code Integer.MAX_VALUE}.
*
* @return the number of key-value mappings in this map
*/
int size();
size()方法,最大返回Integer.MAX_VALUE
,当数量超过这个值依然返回这个值。
与数量无关,HashMap读取性能主要取决于放入HashMap中的key对象的hashCode方法的实现,即此方法返回值导致的Hash冲突的比例,冲突越多,性能越差。
java.util.HashMap的实现是一个标准的hash表+链表结构:
当执行HashMap.put(key, value)的时候:
那么当执行HashMap.get(key)的时候,查询过程也是一样的两步:
所以key.hashCode()导致产生冲突的数量决定了这张HashMap的查询性能。
iteration 进行Map的增删改查是最安全的,因为iteration 是Map的内部类接口,避免了异步造成的数据不同步。
如果不适用迭代器进行Map的删除操作,特别是在并发情况下,很容易出现例如,一个5个元素的map,已经删除了一个元素,在取值的时候依然去取第五个元素的情况。
链接:
Java集合的常见用法你知道多少 https://blog.csdn.net/weixin_35874254/article/details/112366244
LruCache、HashMap和LinkedHashMap的使用 https://blog.csdn.net/WLX10428/article/details/119053394