javaSE复习系列之集合篇-HashMap与Hashtable
来源:互联网 发布:昆明理工大学网络教学 编辑:程序博客网 时间:2024/06/05 20:43
开篇先声明一下,一下观点并非百分之百正确,仅作学习参考。
HashMap 允许将 null 作为一个 entry 的 key 或者 value,而 Hashtable不允许key和value任何一方为空。
来看Hashtable的put方法的源代码:
public synchronized V put(K key, V value) { // 如果value==null时,抛出空指针异常。 if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. Entry tab[] = table; int hash = hash(key); int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { V old = e.value; e.value = value; return old; } } modCount++; if (count >= threshold) { // Rehash the table if the threshold is exceeded rehash(); tab = table; hash = hash(key); index = (hash & 0x7FFFFFFF) % tab.length; } // Creates the new entry. Entry<K,V> e = tab[index]; tab[index] = new Entry<>(hash, key, value, e); count++; return null; }
put方法中声明了一个Entry类型的数组,将数组变量tab的引用指向了Hashtable的成员变量table,这里采用了transient关键词修饰,
作用是:告诉编译器,table变量需要避开serialization序列化机制,防止被串行化,为什么要用它来修饰暂时没有研究。
private transient Entry<K,V>[] table;
Entry是Hashtable中一个静态内部类,是每一个元素的载体。它实现了Map的内部接口Entry.,接口中定义了以下几个方法:
getKey()
getValue()
setValue(V)
equals(Object)
hashCode()
接着再跟进来研究看一下Entry内部类的源代码吧,
private static class Entry<K,V> implements Map.Entry<K,V> { int hash; final K key; V value; Entry<K,V> next; protected Entry(int hash, K key, V value, Entry<K,V> next) { this.hash = hash; this.key = key; this.value = value; this.next = next; } protected Object clone() { return new Entry<>(hash, key, value, (next==null ? null : (Entry<K,V>) next.clone())); } // Map.Entry Ops public K getKey() { return key; } public V getValue() { return value; } public V setValue(V value) { if (value == null) throw new NullPointerException();//这里可以看出value为空会抛出空指针异常 V oldValue = this.value; this.value = value; return oldValue; } public boolean equals(Object o) { if (!(o instanceof Map.Entry)) return false; Map.Entry<?,?> e = (Map.Entry)o; //这里使用了java的泛型通配符,将传进来的对象强转为父接口Mao.Entry接口的声明变量 return key.equals(e.getKey()) && value.equals(e.getValue());//key和value两个都要对比。 } public int hashCode() { // 下面使用了Objects工具类提供的hashCode方法,我还是贴出这个方法的源代码吧 // return o != null ? o.hashCode() : 0; return (Objects.hashCode(key) ^ Objects.hashCode(value)); } public String toString() { return key.toString()+"="+value.toString(); } }
可能有些人会有疑问为什么key的空指针异常在哪里抛出呢?我debug的时候是在Thread中抛出。
private void dispatchUncaughtException(Throwable e) { getUncaughtExceptionHandler().uncaughtException(this, e); }
说到这里,我想又得长篇大论了,为什么Hashtable的key空指针跑到Thread里面抛出异常?
我们不妨将debug进行下去,f5走起
public UncaughtExceptionHandler getUncaughtExceptionHandler() { return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group; }
uncaughtExceptionHandler此时是null,于是返回group,继续
public void uncaughtException(Thread t, Throwable e) { if (parent != null) { parent.uncaughtException(t, e); } else { Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler(); if (ueh != null) { ueh.uncaughtException(t, e); } else if (!(e instanceof ThreadDeath)) { System.err.print("Exception in thread \"" + t.getName() + "\" "); e.printStackTrace(System.err); } } }
空指针就是在这里抛出的,我没有再做深入研究。
Hashtable继承自Dictionary类,而 HashMap 是Java1.2引进的 Map interface的一个实现。 最大的不同是,Hashtable 的方法是 Synchronize 的,而 HashMap 不是,在多个线程访问 Hashtable 时,不需要自己为它的方法实现同步,而 HashMap 就必须为之提供外同步。
就 HashMap 与 HashTable 主要从三方面来说。
一.历史原因:Hashtable 是基于陈旧的 Dictionary 类的,HashMap 是 Java 1.2引进的 Map 接口的一个实现
二.同步性:Hashtable 是线程安全的,也就是说是同步的,而 HashMap 是线程序不安全的, 不是同步的
三.值:只有 HashMap 可以让你将空值作为一个表的条目的 key 或 value
- javaSE复习系列之集合篇-HashMap与Hashtable
- javase复习系列之--多线程篇
- Java 集合:Map 系列(HashMap,HashTable)
- Java 集合:Map 系列(HashMap,HashTable)
- Java之HashMap与HashTable
- JavaSE基础知识学习—集合之HashMap
- JavaSE复习之四 基础知识:集合
- javase重新开始系列之集合与泛型
- 集合之LinkedList、Vector、HashMap、Hashtable
- Java Map集合之HashMap、HashTable
- Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
- Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
- Java 集合系列之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
- Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
- Java 集合系列14之 Map总结(HashMap, Hashtable, TreeMap, WeakHashMap等使用场景)
- 面试系列-HashTable与HashMap的区别
- 数据结构探险之HashMap 与Hashtable
- Java面试题之HashMap与HashTable
- Java中继承thread类与实现Runnable接口的区别
- dom4j 最常用最简单的用法
- 递归思想
- 内存问题
- Hadoop2.4.1学习笔记(一)之ssh远程登录原理
- javaSE复习系列之集合篇-HashMap与Hashtable
- x264参数中文详解(X264 Settings)
- LitePal的存储操作(二)
- eclipse 中文注释的乱码问题解决方案
- Azure RBAC(Roles Based Access Control)正式上线了
- git在一个分支上修改了代码但是不想commit到本地git库,需要切换一个分支去修改代码,这个时候也可以使用git stash
- PHP 统计字符串中字符出现的个数
- windows下Nginx+Tomcat
- Android签名机制之---签名过程详解