浅谈HashMap(1)

Java为数据结构中的映射定义了一个接口java.util.Map,然后HashMap是这个接口其中的一个实现类 他的内部实现在java1.7及之前是一种叫链表散列的数据结构,也就是数组加链表的数据结构实现的

 

当调用Put方法存值时,会先调用hashcode方法计算出key的哈希值,然后将keyvalue放入这个哈希值对应的数组下的链表中.HashMap允许一条记录的键为null,允许多条记录的值为null,因为在计算哈希值时,会先判断key是否为Null,如果为null 就将数据放入map的首位)

当调用get方法取值时 会根据key值计算出hashcode去查找对应的数组,然后在数组中再根据key值查询对应的value

简单来说 哈希算法可以将数据分到一排哈希桶中,将哈希值相同的数据放到同一个

哈希桶,如果俩个对象相同 hash值肯定相同,但是hash值相同俩个对象不一定相同 比如”Ea”和”FB” hash值相同,但是对象不同

1.为什么HashMap能保证Key的唯一性?

因为HashMapput存数据时会先通过keyhash值找到数据在哪个数组元素对应的链表中,然后遍历链表找到key值对应的value,如果已经有值就进行修改,这样就使key值变为了唯一的(自定义对象需要重写hashCodeEquals方法)

为什么要重写hashCode方法:因为在默认的情况下hashCode方法是将对象的存储地址进行映射,当新建俩个自定义对象时不同的对象存储地址肯定不同,所以所得的hashCode值也肯定不同

为什么要重写equals方法:因为要判断两个对象在逻辑上是否相等,需要根据类的成员变量来判断两个类的实例是否相等,而继承Object中的equals方法只能判断两个引用变量是否是同一个对象

2.为什么HashMap需要使用哈希算法?

因为效率.如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000equals方法。这显然会大大降低效率。计算哈希值相当于计算索引,通过索引去存取值可以大大的加快运算的效率 因为实际调用equals方法的次数就大大降低了,几乎只需要一两次

 

 

拓展:

Hashmap,HashTable,LinkedHashMap,TreeMap

(1) HashMap:它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 HashMap最多只允许一条记录的键为null,允许多条记录的值为nullHashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以用 CollectionssynchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap

(2) HashtableHashtable是遗留类,很多映射的常用功能与HashMap类似,不同的是它承自Dictionary类,并且是线程安全的,任一时间只有一个线程能写Hashtable,并发性不如ConcurrentHashMap,因为ConcurrentHashMap引入了分段锁。Hashtable不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换。

(3) LinkedHashMapLinkedHashMapHashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。

(4) TreeMapTreeMap实现SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。如果使用排序的映射,建议使用TreeMap。在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常。

对于上述四种Map类型的类,要求映射中的key是不可变对象。不可变对象是该对象在创建后它的哈希值不会被改变。如果对象的哈希值发生变化,Map对象很可能就定位不到映射的位置了。

 

-----------------------------------------------------------------------------------------------------------------------------

Java 1.8数组+链表+红黑树

当链表长度大于默认值8,就会默认转换为红黑树 增加HashMap的性能

-----------------------------------------------------------------------------------------------------------------------------

 

ConcurrentHashMap(king可瑞特) 分段锁

对数据使用分段加载同步锁,默认可以同时并发16个线程去同时操作数据,相比Hashtable的同步并发量更高,效率也更快

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章