HashMap及其相关知识点

一、HashMap插入与删除

通过将key转换为hashCode(int),通过hashCode计算下标,int index = hashCode & (length - 1),从而实现插入与删除。

二、Hash冲突

Java8之前:通过数组+链表的数据结构解决hash冲突,头插法。

Java8之后:数据+链表+红黑树,尾插法,因为单链表如果元素太多,查找效率低。

优化:HashMap的容量必须是2的次幂,减少hash冲突。

三、HashMap线程安全问题

HashMap是线程不安全的。

多线程中可以使用HashTable,它是线程安全的。

HashTable的问题:

synchronized加在方法上,方法锁,锁住整个数组+链表/红黑树,效率低。synchronized是对象内置锁,由JVM管理开锁&关锁。多个线程同时操作HashTable,只有一个线程能获得锁往下执行。

多线程中可以使用ConcurrentHashMap,它也是线程安全的。

synchronized加在代码块上,代码块锁,锁住链表,只有在多个线程同时操作一个链表是才会产生性能问题。

四、HashMap与SparseArray的对比

结论:SparseArray占用内存更小,get/put/remove性能更优。

1.HashMap

1.1.时间

put:

  • 根据 key 计算hashCode值(int),hashCode与数组长度相与(&)计算元素的index(下标),如果index相同,就会产生hash冲突。
  • 比较hashCode和key是否相等,如果相等,替换旧值,否则插入新的节点,形成链表(耗时
  • 如果数组的容量已经达到阈值,则进行数组的扩容,根据hash值计算元素下标,把旧数组元素复制到新数组中(耗时)。
  • 简单来说就是插入比对耗时和扩容耗时(rehash)导致HashMap性能相对较差

get:

  • 计算hash值,用hash值计算index与put相同。
  • 如果key相等(==) 或者 hash值相等&&key相等(equals),则返回查到的值,否则返回null。
  • 简单来说也是查找比对耗时

1.2.空间

  • key是任意Object类型,比较耗内存。
  • HashMap有阈值(0.75F),当HashMap的元素数量达到:容量 * 0.75F,数组就需要扩容,浪费了部分内存空间。

2.SparseArray

两个数组:int[] mKeys 和 Object[] mValues。

2.1.时间

put:

二分查找确定key的index(mKeys数组是有序的):

  1. 有该key,替换value;
  2. 没有该key,如果index小于数组长度&&mValues数组对应index位置为DELETE,替换index位置的key和value(删除时mValues数组标记为DELETE);
  3. 上述条件都不满足,插入新的key和value,其后的元素往后移动。

get:

二分查找得到key的index,根据index获取value。

remove:

删除并不是真正的删除,而是标记为删除(mValues数组标记为DELETE),增删多的情况效率高。

总结:效率较高

2.2.空间

mKeys数组是int类型的,更加节省内存。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值