Hashtable的结构,采用的是数据结构中所说的链地址法处理冲突的方法
从上面的结构图可以看出,Hashtable的实质就是一个数组+链表。图中的Entry就是链表的实现,Entry的结构中包含了对自己的另一个实例的引用next,用以指向另外一个Entry。而图中标有数字的部分是一个Entry数组,数字就是这个Entry数组的index。那么往Hashtable增加键值对的时候,index会根据键的hashcode、Entry数组的长度共同决定,从而决定键值对存放在Entry数组的哪个位置。从这种意义来说,当键一定,Entry数组的长度一定的情况下,所得到的index肯定是相同的,也就是说插入顺序应该不会影响输出的顺序才对。然而,还有一个重要的因素没有考虑,就是计算index出现相同值的情况。譬如代码中 "sichuan" 和 "anhui",所得到的index是相同的,在这个时候,Entry的链表功能就发挥作用了:put方法通过Entry的next属性获得对另外一个Entry的引用,然后将后来者放入其中。根据debug得出的结果,"sichuan", "anhui"的index同为2,"hunan"的index为6,"beijing"的index为1,在输出的时候,会以index递减的方式获得键值对。很明显,会改变的输出顺序只有"sichuan"和"anhui"了,也就是说输出只有两种可能:"hunan" - "sichuan" - "anhui" - "beijing"和"hunan" - "anhui" - "sichuan" - "beijing"。以下是运行了示例代码之后,Hashtable的结果:
在Hashtable的实现代码中,有一个名为rehash的方法用于扩充Hashtable的容量。很明显,当rehash方法被调用以后,每一个键值对相应的index也会改变,也就等于将键值对重新排序了。这也是往不同容量的Hashtable放入相同的键值对会输出不同的键值对序列的原因。在Java中,触发rehash方法的条件很简单:hahtable中的键值对超过某一阀值。默认情况下,该阀值等于hashtable中Entry数组的长度×0.75。
自 Java 2 平台 v1.2 以来,此类已经改进为可以实现 Map,因此它变成了 Java Collections Framework 的一部分。与新集合的实现不同,Hashtable 是同步的。
由迭代器返回的 Iterator 和由所有 Hashtable 的“collection 视图方法”返回的 Collection 的 listIterator 方法都是快速失败 的:在创建 Iterator 之后,如果从结构上对 Hashtable 进行修改,除非通过 Iterator 自身的移除或添加方法,否则在任何时间以任何方式对其进行修改,Iterator 都将抛出 ConcurrentModificationException。因此,面对并发的修改,Iterator 很快就会完全失败,而不冒在将来某个不确定的时间发生任意不确定行为的风险。由 Hashtable 的键和值方法返回的 Enumeration 不 是快速失败的。
注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误做法:迭代器的快速失败行为应该仅用于检测程序错误。
Hashtable中的Entry数据结构
put方法:key的hash值不同但是可能放入的index相同,并且在放入之前需要判断
2 return this.<K>getEnumeration(KEYS);
3 }
4
5 private <T> Enumeration<T> getEnumeration(int type) {
6 if (count == 0) {
7 return (Enumeration<T>)emptyEnumerator;
8 } else {
9 return new Enumerator<T>(type, false);
10 }
11 }
12
13 public synchronized Enumeration<V> elements() {
14 return this.<V>getEnumeration(VALUES);
15 }
16
17Enumerator是Hashtable定义的一个内部类
18 private class Enumerator<T> implements Enumeration<T>, Iterator<T> {
19 Entry[] table = Hashtable.this.table;//访问宿主类的成员变量
20 int index = table.length;
21 Entry<K,V> entry = null;
22 Entry<K,V> lastReturned = null;
23 int type;
24
25 /**
26 * Indicates whether this Enumerator is serving as an Iterator
27 * or an Enumeration. (true -> Iterator).
28 */
29 boolean iterator;
30
31 /**
32 * The modCount value that the iterator believes that the backing
33 * Hashtable should have. If this expectation is violated, the iterator
34 * has detected concurrent modification.
35 */
36 protected int expectedModCount = modCount;
37}
38内部类中提供了访问了hashtable中的entry数组的方法.
39在实现Iterator接口中的方法时使用了expectedModCount变量来判断是否有并发修改而导致fast-fail,而在Enumeration的接口方法实现中没有判断
40
41
42
43 public Set<K> keySet() {
44 if (keySet == null)
45 keySet = Collections.synchronizedSet(new KeySet(), this);
46 return keySet;
47 }
48 private class KeySet extends AbstractSet<K> {
49 public Iterator<K> iterator() {
50 return getIterator(KEYS);
51 }
52 public int size() {
53 return count;
54 }
55 public boolean contains(Object o) {
56 return containsKey(o);
57 }
58 public boolean remove(Object o) {
59 return Hashtable.this.remove(o) != null;
60 }
61 public void clear() {
62 Hashtable.this.clear();
63 }
64 }
65内部类KeySet中有iterator接口方法的实现,调用的宿主类的getIterator(KEYS)
66 private <T> Iterator<T> getIterator(int type) {
67 if (count == 0) {
68 return (Iterator<T>) emptyIterator;
69 } else {
70 return new Enumerator<T>(type, true);
71 }
72 }
73getIterator中new 了一个新的内部类Enumerator的对象,最终使用Enumerator来访问hashtable的entry数组,能不能在内部类中直接创建一个内部类的的实例???
74
75
76
77 public Collection<V> values() {
78 if (values==null)
79 values = Collections.synchronizedCollection(new ValueCollection(),
80 this);
81 return values;
82 }
83ValueCollection也是一个内部类,结构和KeySet功能差不多
84 public Set<Map.Entry<K,V>> entrySet() {
85 if (entrySet==null)
86 entrySet = Collections.synchronizedSet(new EntrySet(), this);
87 return entrySet;
88 }
89EntrySet也是内部类,结构和KeySet功能差不多
相关推荐
Java中的`Hashtable`类是Java集合框架的一部分,它是一个基于哈希表的Map接口实现。这个数据结构允许我们以键值对的形式存储数据,并且提供了快速的插入、删除和查找操作。`Hashtable`是线程安全的,因此可以在多...
《实战应用Java算法分析与设计(链表、二叉树、哈夫曼树、图、动态规划、HashTable算法)》 课程简介: 算法分析与设计Java版,是一套实用型算法课程。通过本课程的学习,学员可以掌握以下技术点:线性结构与顺序表...
在Java编程语言中,`HashMap`和`HashTable`都是实现键值对存储的数据结构,但它们之间存在一些显著的区别,这些区别主要体现在线程安全性、性能、null值处理以及一些方法特性上。以下是对这两个类的详细分析: 1. ...
通过阅读和分析这份代码,我们可以深入了解易语言如何借鉴Java的HashTable实现哈希表,以及易语言特有的编程风格和技巧。这有助于提升我们对易语言的理解,并且能够运用到自己的项目中,优化数据存储和检索的效率。
Java集合专题总结:HashMap和HashTable源码学习和面试总结 本文总结了Java集合专题中的HashMap和HashTable,涵盖了它们的源码学习和面试总结。HashMap是一种基于哈希表的集合类,它的存储结构是一个数组,每个元素...
在Java编程语言中,`Hashtable`是一个非常基础且重要的数据结构,它属于集合框架的一部分,提供了键值对(key-value pairs)的存储功能。...通过分析压缩包中的示例代码,你可以更好地掌握`Hashtable`的实际应用。
接下来,我们将详细探讨`Hashtable`和`HashMap`之间的区别,并分析它们各自的优缺点。 #### 1. 线程安全性 - **Hashtable**: 是线程安全的。`Hashtable`的所有关键操作(如`put()`、`get()`)都是同步的,这意味着...
本文将重点分析这三种数据结构之间的区别,特别是针对`HashTable`不支持空键值对而`HashMap`支持这一点进行深入探讨。 #### 二、HashTable `HashTable`是基于哈希表实现的一个线程安全的`Map`容器,它不允许`key`...
《实战应用Java算法分析与设计(链表、二叉树、哈夫曼树、图、动态规划、HashTable算法)》 算法分析与设计Java版,是一套实用型算法课程。通过本课程的学习,学员可以掌握以下技术点:线性结构与顺序表、单向链表、...
本文将详细分析四种常用的`Map`实现类:`HashMap`, `LinkedHashMap`, `TreeMap`以及`HashTable`之间的区别。 #### 1. HashMap `HashMap`是一种基于哈希表实现的`Map`接口,提供了一个非同步的、允许使用`null`键和...
【Java容器之Hashtable源码分析】 在Java编程中,`Hashtable`是一个古老的容器类,它继承自`Dictionary`接口,并实现了`Map`接口,同时也实现了`Cloneable`和`Serializable`接口。`Hashtable`与`HashMap`类似,都是...
通过上述分析,我们了解到如何使用Java对`HashTable`中的元素进行按键或值的排序。这通常涉及到将`Hashtable`的条目集转换为数组,然后使用自定义比较器对数组进行排序。这种方法不仅适用于`Hashtable`,也适用于...
│ Java面试题11.HashMap和HashTable的区别.mp4 │ Java面试题12.实现一个拷贝文件的类使用字节流还是字符串.mp4 │ Java面试题13.线程的实现方式 怎么启动线程怎么区分线程.mp4 │ Java面试题14.线程并发库和线程池...
Java中的`Hashtable`和`HashMap`都是`Map`接口的实现类,它们都用于存储键值对数据。然而,这两个类在设计和功能上有显著的差异,这些差异主要体现在线程安全性、空值处理、迭代器类型以及哈希表的初始化和扩容策略...
本课件集合主要针对Java中的数据结构及其算法进行了深入的探讨和分析。 在"java数据结构课件与分析"中,我们可以期待学习到以下几个关键的知识点: 1. **数组**:Java中的基础数据结构,用于存储固定数量的相同...
本篇将详细讲解如何在Java中读取`properties`文件,并通过提供的`SysPropertiesUtil.java`源代码进行分析。 1. `properties`文件简介: `properties`文件是Java中的配置文件,它以键值对的形式存储数据,键和值...
2. **集合框架**:Java集合框架是面试的重点,包括List(ArrayList、LinkedList、Vector)、Set(HashSet、TreeSet)和Map(HashMap、TreeMap、Hashtable)。了解它们的特点、区别及应用场景,如线程安全、遍历方式...
Java中的HashMap和HashTable是两种常见的基于哈希表的数据结构,它们在使用场景、线程安全性、数据处理方式以及API设计等方面存在显著差异。下面将详细分析这些区别。 首先,从继承关系来看,HashMap和HashTable的...
Java的JVM调优也是一个高阶知识点,它通常涉及垃圾回收(GC)、内存泄漏的分析以及性能监控等。掌握JVM调优技巧可以确保Java应用程序在高负载下依然能稳定运行。 在安全方面,SQL注入是需要掌握的知识点。为了防止...