Hashtable

Hashtable是原始的java.util的一部分,属于一代集合类,是一个Dictionary具体的实现 。Java1.2重构的Hashtable实现了Map接口,因此,Hashtable现在集成到了集合框架中。它和HashMap类很相似。

Hashtable与HashMap的区别

  • 1)Hashtable属于一代集合,继承了Dictionary类,也实现了Map接口,HashMap属于二代集合,实现与Map接口,没有与Dictionary类产生关系;
  • 2)Hashtable支持iterator遍历(Map接口中的),也支持Enumeration遍历(Dictionary),HahsMap只支持iterator遍历
  • 3)Hashtable与HashMap底层都是采用hash表这种数据结构,JDK8对HashMap进行了优化(引入红黑树),但并没有对Hashtable进行优化;
  • 4)HashMap默认的数组大小是16,Hashtable则是11,两者的负载因子都是0.75,并且都允许传递初始化的数组大小和负载因子
  • 5)HashMap对null key和null value进行了特殊处理,可以存储null key和null value,Hashtable则不能存储null key和null value;
  • 6)当HashMap存储的元素数量>数组容量*负载因子,数组扩容至原来的2倍,Hashtable则是2倍+1;
  • 7)HashMap在添加元素时使用的是:元素本身的hash算法 ^ (元素本身的hash算法 >>> 16),而Hashtable则是直接采用元素本身的hash算法;

Tips:​​>>​​​代表有符号位移,​​>>>​​代表无符号位移;

  • 8)HashMap在使用foreach迭代时不能对元素内容进行增删,否则触发并发修改异常。Hahstable中支持Enumeration迭代,使用Enumeration迭代元素时,可以对集合进行增删操作;
  • 9)Hashtable是线程安全的,效率低,安全性高;HashMap是线程不安全的,效率高,安全性低;

1)测试存储Null key和Null value:

package com.dfbz.hashtable;

import java.util.HashMap;
import java.util.Hashtable;

/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo02_HashMap与Hashtable的区别_null问题 {
public static void main(String[] args) {
HashMap<Integer, String> hashMap = new HashMap<>();
/*
HashMap对null key和null value
并且,HashMap对null key做了特殊处理,HashMap永远将Null key存储在第0位数组上
*/
hashMap.put(1, null);
hashMap.put(null, "大闸蟹");

System.out.println(hashMap); // {null=大闸蟹, 1=null}
}

public static void test1(){
Hashtable<Integer, String> hashtable = new Hashtable<>();

// Hashtable存储null key和null value的时候会出现空指针异常: Exception in thread "main" java.lang.NullPointerException
hashtable.put(1, null);
hashtable.put(null, "大闸蟹");
}
}

2)测试并发修改异常问题:

package com.dfbz.hashtable;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Set;

/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo03_HashMap与Hashtable的区别_并发修改问题 {
public static void main(String[] args) {

Hashtable<Integer, String> hashtable = new Hashtable<>();
hashtable.put(1, "拌粉");
hashtable.put(2, "汤粉");
hashtable.put(3, "炒粉");
hashtable.put(4, "泡粉");

Enumeration<Integer> keys = hashtable.keys();

while (keys.hasMoreElements()) {
Integer key = keys.nextElement();

if (key == 2) {
/*
Hashtable在使用Enumeration遍历时,允许对集合进行增删操作
注意: Hashtable使用foreach迭代也不能对元素进行增删操作
*/
hashtable.put(5, "扎粉");
// hashtable.remove(3);
}
}

System.out.println(hashtable);
}

/**
* hashMap在使用foreach迭代时不允许对集合进行增删等操作
*/
public static void test1() {
HashMap<Integer, String> hashMap = new HashMap<>();

hashMap.put(1, "拌粉");
hashMap.put(2, "汤粉");
hashMap.put(3, "炒粉");
hashMap.put(4, "泡粉");

Set<Integer> keys = hashMap.keySet();

for (Integer key : keys) {
if (key == 2) {
// hashMap在迭代时不允许对集合进行增删等操作
hashMap.remove(3);
// hashMap.put(5, "扎粉");
}
}
}
}

Dictionary类

Dictionary类是一代集合中的双列集合顶层类,Dictionary类中的方法都是双列集合中最基本的方法;严格意义来说Java中所有的双列集合都应该继承与Dictionary类,但Java2推出了一系列二代集合,其中二代集合中的Map接口也已经替代了Dictionary接口,成为双列集合的顶层接口,因此Dictionary接口下面没有太多的实现类;

Tips:目前JDK已经不推荐使用Dictionary类了;

  • Dictionary接口方法如下:

方法

说明

​ Enumeration<V> elements()​

返回此字典中值的枚举。

​ V get(Object key)​

返回该字典中键映射到的值。

​boolean isEmpty()​

检测该字典是否为空。

​ Enumeration<K> keys()​

返回此字典中键的枚举。

​ V put(K key, V value)​

添加一对key,value到字典中

​ V remove(Object key)​

根据对应的key从字典中删除value。

​ int size()​

返回此字典中的条目数。

  • 方法测试:
package com.dfbz.hashtable;

import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;

/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01_Hashtable基本使用 {
public static void main(String[] args) {
Dictionary<Integer, String> hashtable = new Hashtable<>();

hashtable.put(1, "南昌拌粉");
hashtable.put(2, "粉蒸肉");
hashtable.put(3, "福羹");
hashtable.put(4, "藜蒿炒腊肉");
hashtable.put(5, "瓦罐汤");

String s1 = hashtable.get(3);
System.out.println(s1); // 福羹

String s2 = hashtable.remove(2);
System.out.println(s2); // 粉蒸肉

System.out.println(hashtable); // {5=瓦罐汤, 4=藜蒿炒腊肉, 3=福羹, 1=南昌拌粉}

System.out.println("-------------");

// 获取到Hashtable的所有key
Enumeration<Integer> keys = hashtable.keys();
while (keys.hasMoreElements()){
Integer key = keys.nextElement();
System.out.println(key);
}

System.out.println("-------------");

// 获取到Hashtable的所有value
Enumeration<String> vals = hashtable.elements();
while (vals.hasMoreElements()){
String val = vals.nextElement();
System.out.println(val);
}

System.out.println("-----------------");
System.out.println(hashtable.size()); // 4
}
}