java集合Map接口中hashMap,Hashtable,LinkHashMap分析比较

Map接口

public interface Map<K,V>
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
1、键值对存储一组对象
2、键是唯一不重复的,值可以重复
3、具体的实现类:hashMap、Hashtable、LinkHashMap、TreeMap
4、hashMap与Hashtable区别

hashMap类
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

hashMap实现原理:
1、基于哈希表(数组+链表+二叉树(红黑树),1.8以前是数组+链表)
什么是哈希表?
这个是因为存储数据的方式被称为哈希(算法)
Object类中hashCode方法是一个本地方法:表示此方法的具体实现是由C、 C++来实现的,哈希值()
同一个对象,我们要保证hashCode值 是相同的,如果不同那么此对象在哈希表中会有问题? (内存泄露问题)

JAVA有没有内存泄露问题?
什么叫内存泄露?由于对象的运行过程中,hashCode不同, 导致该对象在哈希表中无法找到

2、默认加载因子为0.75,表示数组容量达到75%会扩容,默认数组的大小是16(1<<4),最大值(1<<30)约是整数最大值的一半。

3、把对象存储到哈希表中,如何存储?
把key对象通过hash()方法计算hash值,然后用这个hash值对数组长度取余(默认16),来决定该对KEY对象在数组中存储的位置,当这个位置有多个对象时,以链表结构存储,jdk1.8后,当链表长度大于8时,并且键值对的总数大于64,链表将转换为红黑树结构存储,这样的目的是为了取值更快,存储的数据量越大,性能的表现越明显。在哈希表扩容时,如果发现链表长度小于6,并且键值对的总数大于64,则会由树重新退化为链表。

4、扩充原理: 当数组容量超过75%,那么表示该数值需要扩充,如何扩充?
扩充算法: 当前数组容量<<(相当于四乘2),扩大1倍,扩充次数过多,会影响性能,每次扩充表示哈希表重新散列(重新计算每个对象的存储位置),我们在开发中尽量要减少扩充次数带来的性能问题

5、性能不安全,适合在单线程中使用

链表与二叉树的转化条件: 是键值对的总数大于64时
1、在扩容时,当哈希表中数组同-一个位置的链表长度大于8时(阀值),那么会把链表转换成红黑树,来提高查询效率。
2、在扩容时,当哈希表中数组同一个位置的链表长度小于6时(阀值),那么会把红黑树转换成链表,来提高查询效率|。
阀值为什么是8和6? (防抖) 减少链表与二叉树之间的转换频率,避免影响性能

哈希表存储数据的算法:
通过计算key对象的hashCode值,来确认key对象在哈希表数组中的存储位置,目的是为了可以通过计算hash值快速的查找对象
同一个对象,hashCode值相同, 不同的对象,hashCode可能相同

使用hashCode计算对象的hash值
return (key = null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

怎么扩容?初始化大小?
1.在第一次put数据的时候初始化
2、在put方法中实现,扩容算法是oldCap << 1表示乘于2
3、每次扩容哈希表,会导致所有已存储的对象重新计算哈希值,存储到新的哈希表中(重新散列)
所以在hashMap中,对象所在的位置不保证永远不变(无序),重新散列会导致重新计算所有对象,消耗性能
在可预知的情况下,散列次数越少越好。
优点:取值快,数据量越大越明显
缺点:线程不安全,避免频繁散列(rehash)
合理的使用new HashMap<>(initialCapacity);初始容量,来减少散列

重写hashCode的原则: 参与hashCode运算的属性值不能在运行期发生变化

内存泄漏和内存溢出
内存泄漏:对象在内存中存在,不是垃圾对象,有引用,但又找不到,越来越多的这样的对象,内存泄漏过多会导致内存溢出
内存溢出:内存被用完了,再放放不进去

代码示例:
hashMap类使用及四种遍历方式(Hashtable与LinkHashMap遍历方式也相同)

package com.booy;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapDemo {
   
	public static void main(String[] args) {
   
		Map
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值