- 浏览: 209728 次
- 性别:
- 来自: 哈尔滨
文章分类
- 全部博客 (267)
- java.lang (8)
- 问题汇总 (21)
- 异常记录 (20)
- 功能实现 (19)
- 面试总结 (25)
- 技巧总结 (8)
- 常用代码 (4)
- 编程习惯 (3)
- 编码规则 (3)
- java.util (10)
- java.io (1)
- JavaWeb (9)
- MySQL (16)
- SVN (3)
- MyBatis (11)
- Velocity (7)
- 其他知识 (10)
- 人生哲理 (1)
- 人生故事 (1)
- 自我感悟 (1)
- shiro (3)
- 基础知识 (0)
- 问题总结 (1)
- Spring 标签 (1)
- Spring (3)
- 点滴生活 (1)
- DOS (1)
- CAS (4)
- Linux (9)
- Storm (6)
- Shell (1)
- regex (1)
- Collection (4)
- poi (1)
- 经典语句 (1)
- NIO (5)
- concurrent (14)
- RPC (1)
- zookeeper (3)
- 待整理 (2)
- Hadoop (9)
- RabbitMq (2)
- flume (1)
- hive (7)
- hbase (4)
- kafka (1)
- scala (1)
- GC (0)
- java.util.concurrent.atomic (1)
- java.lang.ref (6)
- JVM (2)
- algorithm (1)
- conception (1)
- java key word (1)
- sun.misc (1)
最新评论
Hashtable
一、对比HashMap
1.
项目 | HashMap | Hashtable |
默认容量 | 16 | 11 |
负载因子 | 0.75 | 0.75 |
null值 | 允许key/value为空 | 不允许key/value为空(put操作时报空指针异常) |
扩容 | length*2 | length*2+1 |
安全 | 线程不安全 | 线程安全 |
extends | AbstractMap | Dictionary |
容量 | >=1 | 2^n |
2.负载因子
过低,空间利用率低,频繁的扩容
过高,寻址时间增加,key value 的多了;
3.快速失败
modCount
在遍历过程中,如果 modCount > expectedCount
throw new ConcurrentModificationException
二、类定义
1.源码
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, java.io.Serializable
三、属性
1.源码
/** * The hash table data. */ // Entry 的数组,Entry private transient Entry[] table; /** * The total number of entries in the hash table. */ // 容量 private transient int count; /** * The table is rehashed when its size exceeds this threshold. (The * value of this field is (int)(capacity * loadFactor).) * * @serial */ // 临界值 private int threshold; /** * The load factor for the hashtable. * * @serial */ // 负载因子 private float loadFactor; /** * The number of times this Hashtable has been structurally modified * Structural modifications are those that change the number of entries in * the Hashtable or otherwise modify its internal structure (e.g., * rehash). This field is used to make iterators on Collection-views of * the Hashtable fail-fast. (See ConcurrentModificationException). */ // 修改次数 private transient int modCount = 0; /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = 1421746759512286392L;
四、构造方法
1.
// 初始化容量,负载因子 public Hashtable(int initialCapacity, float loadFactor) { // 初始化容量不能小于0 if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); // 负载因子不能小于0且其是 float类型的数据 if (loadFactor <= 0 || Float.isNaN(loadFactor)) throw new IllegalArgumentException("Illegal Load: "+loadFactor); if (initialCapacity==0) // 初始化容量 为任意数字 ,HashMap 要求必须为 2 的 N 次幂 initialCapacity = 1; this.loadFactor = loadFactor; table = new Entry[initialCapacity]; threshold = (int)(initialCapacity * loadFactor); }
2.
// 默认负载因子 0.75 public Hashtable(int initialCapacity) { this(initialCapacity, 0.75f); } /** * Constructs a new, empty hashtable with a default initial capacity (11) * and load factor (0.75). */ // 默认初始化容量 11 public Hashtable() { this(11, 0.75f); }
3.以存在的集合作为参数
/** * Constructs a new hashtable with the same mappings as the given * Map. The hashtable is created with an initial capacity sufficient to * hold the mappings in the given Map and a default load factor (0.75). * * @param t the map whose mappings are to be placed in this map. * @throws NullPointerException if the specified map is null. * @since 1.2 */ public Hashtable(Map<? extends K, ? extends V> t) { // 调用构造方法,初始化容量为 已有集合中的key-value 对数量的 2 倍 this(Math.max(2*t.size(), 11), 0.75f); putAll(t); } // 遍历已有集合,调用put方法,synchronized 关键字,线程安全 public synchronized void putAll(Map<? extends K, ? extends V> t) { for (Map.Entry<? extends K, ? extends V> e : t.entrySet()) put(e.getKey(), e.getValue()); }
五、put()
1.源码
public synchronized V put(K key, V value) { // Make sure the value is not null // value 不允许为空,空指针异常 if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. // 赋值 Entry tab[] = table; // key 不能为空,否则获取 hashcode 时报空指针异常 // 一次hash,key本身的hash值 int hash = key.hashCode(); // 二次计算hash值,再与length 取余,确定存放在数组中的位置 int index = (hash & 0x7FFFFFFF) % tab.length; // 取出index 位置的数据,遍历数组下的链表,判断此 key 是否已存在 // 若已存在,则替换已存在的value值,并返回旧的value值 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; } } // 操作次数加 1 modCount++; // Hashtable 中 Entry 的数量 count 是否大于临界值 if (count >= threshold) { // Rehash the table if the threshold is exceeded // 扩容 rehash(); tab = table; index = (hash & 0x7FFFFFFF) % tab.length; } // Creates the new entry. // 将 tab[index] 位置的链表赋值给 e Entry<K,V> e = tab[index]; // 新增Entry ,将原有的链表放在新加入的Entry 的next 中 // 即 新增的Entry 是放在链表的首位的 tab[index] = new Entry<K,V>(hash, key, value, e); count++; return null; } // Entry 的构造方法 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 void rehash() { // 扩容前的容量 int oldCapacity = table.length; Entry[] oldMap = table; // 扩容后的容量 length*2 + 1 int newCapacity = oldCapacity * 2 + 1; Entry[] newMap = new Entry[newCapacity]; // 操作次数加1 modCount++; threshold = (int)(newCapacity * loadFactor); table = newMap; // 两层循环,外层遍历原数组的总长度,将旧数组依次放入新的数组中 for (int i = oldCapacity ; i-- > 0 ;) { // 获取旧数据中下标 i 处的链表 for (Entry<K,V> old = oldMap[i] ; old != null ; ) { // 获取链表当前位置的元素值 Entry<K,V> e = old; // 指针下移 old = old.next; // 计算存储位置 int index = (e.hash & 0x7FFFFFFF) % newCapacity; // 当前元素指向新的数组中 index 下标位置 e.next = newMap[index]; // 新数组的index 位置指向 e newMap[index] = e; } // 遍历的结果是将链表中的元素倒置放入新的数组中 } }
六、remove()
1.源码
public synchronized V remove(Object key) { Entry tab[] = table; int hash = key.hashCode(); // 定位存储位置 int index = (hash & 0x7FFFFFFF) % tab.length; for (Entry<K,V> e = tab[index], prev = null ; e != null ; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { modCount++; // 若链表中的元素数量 > 1 ,则将前一个Entry.next 指向 当前元素的next if (prev != null) { prev.next = e.next; } else { // 遍历条件 // Entry<K,V> e = tab[index], prev = null // 下一次循环时,进行赋值 prev = e ;若 prev == null // 说明链表中的第一个Entry 即为目标 tab[index] = e.next; } count--; // count表示存放的 Entry的数量 V oldValue = e.value; e.value = null; return oldValue; } }
七、get()
1.源码
public synchronized V get(Object key) { Entry tab[] = table; // key 不能为 null,此处报空指针 int hash = key.hashCode(); 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)) { return e.value; } } return null; }
发表评论
-
Arrays
2017-10-27 22:54 352Arrays 一、总结 1.基于 jdk 1.8 二、a ... -
Collections
2017-10-27 22:40 388Collections 一、总结 1.基于 JDK 1.8 ... -
LinkedList
2017-10-09 21:18 431LinkedList 一、总结 1.基 ... -
Objects
2017-10-08 12:20 398Objects 一、总结 二、equals Obje ... -
RandomAccess
2017-10-08 11:24 382RandomAccess 总结: 1.基于 JDK 1.8 ... -
ArrayList
2017-10-08 10:14 444ArrayList 一、总结 1.基于 JDK 1.8 源 ... -
HashSet
2017-09-24 15:04 342HashSet 一、总结(jdk 1.8.0_131) 1 ... -
HashMap
2017-03-11 17:48 443HashMap jdk-1.8.0 一、总结 允许key ... -
Vector
2017-03-11 14:57 501Vector 一、总结 1.线程安全 二、类 1.源 ...
相关推荐
var hashtable = (Hashtable)serializer.Deserialize(jsonString, typeof(Hashtable)); ``` 2. **Newtonsoft.Json**:这是更流行和功能强大的第三方库,也被称为Json.NET。它的`JsonConvert.DeserializeObject`方法...
### hashMap和hashTable的区别 #### 一、简介与基本概念 `HashMap` 和 `HashTable` 都是 Java 集合框架中非常重要的数据结构,它们都实现了 `Map` 接口,用于存储键值对。尽管它们在功能上有很多相似之处,但在...
哈希表(Hashtable)是.NET框架中的一种常用数据结构,主要用作键值对存储,它提供了快速的数据存取方式。在WinForm应用程序中,我们可能会利用Hashtable来管理各种对象,尤其是在需要高效查找和操作数据时。下面将...
### HashMap与HashTable的区别详解 #### 引言 在Java编程中,`HashMap`与`HashTable`作为两种常用的数据结构,经常被用来存储键值对数据。尽管它们在功能上相似,但在实现细节、性能表现以及使用场景方面存在显著...
在Java编程语言中,集合框架是处理对象数组的重要工具,其中`List`、`ArrayList`、`Vector`、`HashTable`和`HashMap`是五个关键的接口和类,它们各有不同的特性和用途。以下是这些概念的详细解释: 1. **List接口**...
Hashtable hashtable = JsonConvert.DeserializeObject<Hashtable>(json); ``` 上述代码将JSON字符串解析成一个Hashtable对象,键值对可以直接通过键来访问。 接下来,我们讨论JSON到DataTable的转换。同样需要...
在ASP.NET中,Hashtable是一种常用的数据结构,它是一个键值对集合,允许程序员存储和检索对象。本篇文章将深入探讨如何在ASP.NET中遍历Hashtable,以及相关的重要知识点。 首先,理解Hashtable的基本概念至关重要...
HashMap和HashTable底层原理以及常见面试题 HashMap和HashTable是Java中两个常用的数据结构,都是基于哈希表实现的,但它们之间存在着一些关键的区别。本文将深入探讨HashMap和HashTable的底层原理,并总结常见的...
### HashMap与HashTable和HashSet的区别 #### 一、概述 在Java集合框架中,`HashMap`, `HashTable` 和 `HashSet` 是三个重要的数据结构,它们分别实现了`Map`接口和`Set`接口,提供了不同的功能来满足不同的编程...
在Java编程语言中,`Hashtable`是一个非常基础且重要的数据结构,它属于集合框架的一部分,提供了键值对(key-value pairs)的存储功能。`Hashtable`类是线程安全的,意味着在多线程环境下,它能确保数据的一致性和...
Hashtable是C#编程语言中的一种内置数据结构,属于.NET Framework的System.Collections命名空间。它是一个基于散列的键值对集合,允许程序员快速查找、添加和删除元素。在本篇文档中,我们将深入探讨如何在C#中有效...
在Java编程语言中,`Hashtable`是`Collections`框架的一部分,它是一个同步的键值对存储容器。在早期的Java版本中,`Hashtable`并没有直接支持泛型,这意味着你可以在其中存储任何类型的键(`Object`)和值(`Object...
### HashMap与HashTable的区别 在Java编程语言中,`HashMap`和`HashTable`是两种非常重要的数据结构,它们都实现了`Map`接口,并提供了键值对的存储方式。这两种数据结构虽然相似,但在实现细节和使用场景上存在...
哈希表(HashTable)在C#编程语言中是一种常用的数据结构,它允许高效地存储和检索键值对数据。在.NET Framework中,`System.Collections`命名空间提供了`HashTable`类,用于存储和管理这些键值对。下面我们将深入探讨...
### HashMap与Hashtable的区别 在Java编程语言中,`HashMap`和`Hashtable`是两种非常重要的数据结构,它们都用于存储键值对。然而,在实际应用过程中,这两种数据结构有着本质的不同,下面将详细介绍这些差异。 ##...
本文将详细探讨标题所提及的“hashtable序列化与反序列化”,并提供一个基本的示例。 首先,让我们理解什么是序列化。序列化是将对象的状态转换为可存储或可传输的形式的过程。在Java中,对象序列化允许我们将一个...
### Hashtable和HashMap的区别 在Java编程语言中,`Hashtable`和`HashMap`是两种非常重要的数据结构,它们都实现了`Map`接口,用于存储键值对。尽管它们有着相似的功能,但在实现细节和应用场景上存在显著差异。接...
在本篇文章中,我们将深入探讨哈希表的实现,特别是基于C语言的简单实现,参考文件"hashtable.c"和"hashtable.h"。 1. 哈希函数:哈希表的核心是哈希函数,它将输入(键或关键字)转换为数组索引。一个好的哈希函数...
本教程将详细讲解如何使用Java中的Session和Hashtable来实现这一功能。 首先,Session是Web应用程序中用于跟踪用户状态的一种机制。在HTTP协议无状态的特性下,Session为我们提供了在多个请求之间保持用户信息的...