java 基础 ---HashMap、HashTable

HashMap、HashTable区别。

1、HashMap线程不安全,HashTable线程安全;

2、HashMap的键和值都允许null值存在,而HashTable不允许;

3、HashMap的效率高于Hashtable

* Hash table based implementation of the <tt>Map</tt> interface.  This

* implementation provides all of the optional map operations, and permits

* <tt>null</tt> values and the <tt>null</tt> key.  (The <tt>HashMap</tt>

* class is roughly equivalent to <tt>Hashtable</tt>, except that it is

* unsynchronized and permits nulls.)  This class makes no guarantees as to

* the order of the map; in particular, it does not guarantee that the order

* will remain constant over time.

HashMap是一哈种希表(链表的数组)的结构存储。HashMap的底层主要是基于数组和链表来实现的,通过计算散列来决定存储的位置(数组的下标),数组的每一个元素都是一个单链表的头节点。HashMap通过key的hashCode来计算hash值,hash值相同的对象在数组中的位置一样,此时出现hash冲突,HashMap通过链表的方式解决。

使用对象作为HashMap和HashTable的key时,需要去实现对象的hashCode()方法和equals()方法。

决定HashMap性能的2个关键因素:

initial capacity(初始化容量,默认16)和 load factor(加载因子,填满的程度,默认是0.75)。初始化容量必须为2的n次方。加载因子越大,填满的元素越多,空间利用率越高,hash冲突机会越大,链表长度越长,查找效率越低;加载因子越小,填满的元素越少,数据会过于疏散,空间会浪费(很多空间还没用就可能需要扩容),但是hash冲突会减少。

HashMap计算散列(数组下标)的公式:(table.length-1)& hash

HashTable计算散列的公式:(hash & 0x7FFFFFFF) % tab.length(除法散列法)

相比较而言,取模会使用除法效率偏低,HashMap比HashTable效率高的一点表现。因为HashMap计算是使用(table.length-1)& hash。如果length为奇数,则(table.length-1)为偶数,最后一位(二进制)为0,这样通过&计算导致得出的散列值最后一位也为0,即只能为偶数,这样任何hash值都只会被散列到数组的偶数下标位置上,这便浪费了一半的空间,因此,length取2的整数次幂,即是为了使不同hash值发生碰撞的概率较小,也能避免过多的浪费空间使元素在哈希表中均匀地散列。

HashMap的扩容:newCap = oldCap << 1

当元素个数超过数组大小*load factor时,就会进行扩容,容量扩大一倍。即默认情况下,HashMap元素个数超过16*0.75=12时,数组大小扩大到2*16=32,然后需要重新计算每个元素在数组中的位置(length改变导致散列值变化),扩容是需要进行数组复制的,复制数组是非常消耗性能的操作,所以能预知HashMap元素数量时,预设元素个数就能够有效的提高HashMap性能。

HashTable的扩容:int newCapacity = (oldCapacity << 1) + 1;

如何能让HashMap同步:Map m = Collections.synchronizeMap(hashMap);

注意

JDK1.8之前:使用单向链表来存储相同索引值的元素。在最坏的情况下,这种方式会将HashMap的get方法的性能从O(1)降低到O(n)。

在JDK1.8:为了解决在频繁冲突时hashmap性能降低的问题,使用平衡树来替代链表存储冲突的元素。这意味着我们可以将最坏情况下的性能从O(n)提高到O(logn)。

在Java 8中使用常量TREEIFY_THRESHOLD来控制是否切换到平衡树来存储。目前,这个常量值是8,这意味着当有超过8个元素的索引一样时,HashMap会使用树来存储它们。

这一动态的特性使得HashMap一开始使用链表,并在冲突的元素数量超过指定值时用平衡二叉树替换链表。不过这一特性在所有基于hash table的类中并没有,例如Hashtable和WeakHashMap。目前,只有ConcurrentHashMap,LinkedHashMap和HashMap会在频繁冲突的情况下使用平衡树。

在扩充HashMap的时候,不需要像JDK1.7的实现那样重新计算hash,只需要看看原来的hash值新增的那个bit是1还是0就好了,是0的话索引没变,是1的话索引变成“原索引+oldCap”.

既省去了重新计算hash值的时间,而且同时,由于新增的1bit是0还是1可以认为是随机的,因此resize的过程,均匀的把之前的冲突的节点分散到新的bucket了。这一块就是JDK1.8新增的优化点。有一点注意区别,JDK1.7中rehash的时候,旧链表迁移新链表的时候,如果在新表的数组索引位置相同,则链表元素会倒置,但是从上图可以看出,JDK1.8不会倒置。

原文地址:https://www.cnblogs.com/shenjianjun/p/9332852.html

时间: 2024-08-29 19:15:41

java 基础 ---HashMap、HashTable的相关文章

不惑JAVA之JAVA基础 - HashMap

HashMap应该是平时应用开发中或是框架设计中最为常用高效的容器.在介绍HashMap之前,先介绍两个常见的区别.后期会专门介绍CurrentHashMap. hashmap 和 hashtable 区别 HashMap和HashTable有什么区别,一个比较简单的回答是: HashMap是非线程安全的,HashTable是线程安全的. HashMap的键和值都允许有null值存在,而HashTable则不行. 因为线程安全的问题,HashMap效率比HashTable的要高. hashmap

Java基础--HashMap面试题

import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * HashMap问题 * @author 15735400536 * 使用HashMap,如果key是自定义的类,就必须重写hashcode()和equals() * 使用ArrayList,如果元素是自定义的类,要做相等判断,就必须重写hashCode()和equals() */ publ

java基础---HashMap和HashTable的异同之处

1:连个都实现了Map的接口,两者的底层数据结构相同,都是transient修饰的entry数组,transient修饰的变量不会序列化即不会持久化,序列化的过程中不会包含这个变量,这个变量的生命周期仅仅是在用户的调用过程中,不能持久化到内存磁盘中.这样便于一些敏感信息的保存 2:HashMap是不安全的,不能同步,不支持多线程并发,HashTable是安全的,有同步锁,但效率低. 3:HashMap从AbstractMap继承而来,HashTable是从Dictionary继承而来 4:Has

[Java基础]HashMap的那些事

提到HashMap,使用Java语言的人来说,是再熟悉不过了.今天就简单聊聊我们认识的HashMap; 首先我们看一下Java中的HashMap类 public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { private static final long serialVersionUID = 362498820763181265L;

Java基础——HashMap源码分析

本篇介绍的HashMap综合了ArrayList和LinkedList这两个集合的优势,它的底层是基于哈希表实现的,如果不考虑哈希冲突的话,HashMap在增删改查操作上的时间复杂度都能够达到惊人的O(1). 对于HashMap类源码中开头注释翻译: HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了不同步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同.)此类不保证映射的顺序,特别是它不保

java基础-HashMap

jdk7的HashMap实现的思路比较简单,就是一个Entry数组,数组中每个Entry都是一个链表的起点(表头). 1 public V put(K key, V value) { 2 if (table == EMPTY_TABLE) { 3 inflateTable(threshold); 4 } 5 //如果key为null,则将该entry放在第0位 6 if (key == null) 7 return putForNullKey(value); 8 int hash = hash(

java基础----&gt;hashMap的简单分析(一)

HashMap是一种十分常用的数据结构对象,可以保存键值对.它在项目中用的比较多,今天我们就来学习一下关于它的知识. HashMap的简单使用 一.hashMap的put和get方法 Map<String, String> map = new HashMap<>(); map.put("username", "huhx"); map.put("password", "1234"); map.put(nu

java基础-java核心知识库

1.Spring.mvc的优势,原理,流程 2.Mybatis的原理优势 3.集合里面那些对象的原理 4.扩容原理,特别是map的底层 5.Hashmap.Hashtable和cocurrentHashMap的区别,要讲出它们各自的实现原理才行,比如Hashmap的扩容机制.cocurrentHashMap的段锁原理.多线程安全性. 6.几种造线程池的方法,区别 7.线程有哪几种状态,他们是如何转换的 8.Rpc原理,以及大致流程 9.Nio和netty的区别,为什么netty的性能高,nio,

Java基础教程:HashTable与HashMap比较

Java基础教程:HashTable与HashMap比较 1.  关于HashMap的一些说法: a)  HashMap实际上是一个"链表散列"的数据结构,即数组和链表的结合体.HashMap的底层结构是一个数组,数组中的每一项是一条链表. b)  HashMap的实例有俩个参数影响其性能: "初始容量" 和 装填因子. c)  HashMap实现不同步,线程不安全.  HashTable线程安全 d)  HashMap中的key-value都是存储在Entry中的