当前位置: 首页 > news >正文

HashTable详解

一、HashTable简介:这里给出jdk1.8的中文翻译:

  这个类实现了一个hash table,能够map KV。任何非空对象可以被用做KV.

  为了成功从hashtable中存取对象,被当作K的对象必须实现hashCode()和equals()方法。

  一个Hashtable实例有2个能影响其表现的参数:initial capacity(初始容量)和load factor(加载因子)。容量是hash table中桶的数量,初始容量是hash table 被创建时的容量。提示:hash table是开放的:当“哈希碰撞(hash collision)”的情况下,一个单一桶存储多个必须被顺序查找的entry。load factor是一个方法关于多满的hash table被允许得到,在他的容量自动增长之前。初始容量和加载因子仅仅提示了实现。像何时和是否进行rehash的精确的被调用的细节是依赖实现的。

  通常,默认加载因子(.75)提供了时间和空间开销的较好的平衡。更大的值减少了空间开销,但是增加了寻找entry(在大多数hashtable操作中被反映,包括get()和put()方法)的时间开销。

  初始容量控制了奢侈空间和所需rehash操作的平衡,rehash操作是耗时的。rehash将从不发生,如果初始容量比Hashtable将包含的entry最大数除以其加载因子更大。可是,设置初始容量太高会浪费空间。

  如果大量的entry写入Hashtable,创建它通过一个足够大的容量可以允许entry被快速插入,而不是让它执行自动rehash来达到其所需的空间大小。

  给一个创建数字hashtable的实例。它使用数据作为K:

1 Hashtable<String, Integer> numbers = new Hashtable<String, Integer>();
2      numbers.put("one", 1);
3      numbers.put("two", 2);
4      numbers.put("three", 3);

  取值操作,使用以下代码:

 1 Integer n = numbers.get("two"); 2 if (n != null) { 3 System.out.println("two = " + n);}  

  通过collectionsiterator()方法是fail-fast机制的: 如果在iterator被创建后发生结构上的修改,将抛出ConcurrentModificationException异常。从而,在面对同步修改操作,iterator快速利落的失败,而不是冒着风险,不确定的行为和不确定的时间在将来.  

  通过HashtableK和元素方法返回的枚举不是fail-fast机制的。 

  提示:iteratorfail-fast行为不被保证,通常来说,不可能保证防止异步的同步修改方法。Fail-fast iterators尽力抛出ConcurrentModificationException异常,因此,依靠这个异常来保证程序正确性是错误的:这近被用做检测BUG.

 

  作为Java 2 platform v1.2版本, 这个类被改装实现Map接口,成为了Java Collections Framework的成员。不像新的集合实现类, Hashtable是同步的。如果一个线程安全的实现不被需要,建议使用HashMap代替Hashtable 如果一个线程安全的高同步的实现被需要,建议使用 ConcurrentHashMap代替Hashtable。

    ----------------------------  以上便是jdk1.8中ArrayList的中文翻译  ----------------------------

二、HashTable数据结构:

  1.基本结构:可见其实一个数据链表。

private transient Entry<?,?>[] table;
//Entry的结构方法
private static class Entry<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Entry<K,V> next;
        //...等等操作不一列举
}

   2.GET方法:

 1  public synchronized V get(Object key) {
 2         Entry<?,?> tab[] = table;
 3         int hash = key.hashCode();
 4         int index = (hash & 0x7FFFFFFF) % tab.length;
 5         for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
 6             if ((e.hash == hash) && e.key.equals(key)) {
 7                 return (V)e.value;
 8             }
 9         }
10         return null;
11 }

  3.PUT方法:

  public synchronized V put(K key, V value) {
        // 确保值非空
        if (value == null) {
            throw new NullPointerException();
        }

        // 确保K在hashtable中不存在。
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        return null;
    }

  4.rehash方法:增加容量并且在内部重组hashtable,为了完成和进入它的entry更快。这个方法被自动调用当在hashtableK的数量超过这个hashtable的容量和加载因子。

@SuppressWarnings("unchecked")
    protected void rehash() {
        int oldCapacity = table.length;
        Entry<?,?>[] oldMap = table;

        // overflow-conscious code
        int newCapacity = (oldCapacity << 1) + 1;
        if (newCapacity - MAX_ARRAY_SIZE > 0) {
            if (oldCapacity == MAX_ARRAY_SIZE)
                // Keep running with MAX_ARRAY_SIZE buckets
                return;
            newCapacity = MAX_ARRAY_SIZE;
        }
        Entry<?,?>[] newMap = new Entry<?,?>[newCapacity];
        modCount++;
        threshold = (int)Math.min(newCapacity * loadFactor, MAX_ARRAY_SIZE + 1);
        table = newMap;

        for (int i = oldCapacity ; i-- > 0 ;) {
            for (Entry<K,V> old = (Entry<K,V>)oldMap[i] ; old != null ; ) {
                Entry<K,V> e = old;
                old = old.next;

                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
                e.next = (Entry<K,V>)newMap[index];
                newMap[index] = e;
            }
        }
}

三、hashtable的性质,参见hashtable的结构:

  1.hashtable不接受NULL值;

  2.hashtable是线程同步的;

  3.capacity扩张方法: newCapacity = (oldCapacity << 1) + 1;

  4.初始容量:this(11, 0.75f);

转载于:https://www.cnblogs.com/zpdMulti/p/596957458_qq5.html

相关文章:

  • 《Fluid Engine Development》 学习笔记3-光滑粒子流体动力学
  • Express 相关整合
  • Set集合学习
  • redis与lua
  • 并发数和TPS的理解
  • java 过滤list的几种方式
  • java中的重载(overload)和重写(override)区别
  • 这是一套Java菜鸟到大牛的学习路线之高级教程,由工作了10年的资深Java架构师整理。...
  • 雷林鹏分享:PHP 多维数组
  • 联系我过户这些快到期的域名
  • Maven使用过程中遇到的问题,及解决方案
  • linux磁盘管理
  • spring配置中classpath: 与classpath*:的区别
  • 虚拟机(Virtual Machine)和容器(Container)的对比
  • Linux第四章 进程
  • 《Javascript数据结构和算法》笔记-「字典和散列表」
  • css的样式优先级
  • exif信息对照
  • HTML-表单
  • HTML中设置input等文本框为不可操作
  • Java 23种设计模式 之单例模式 7种实现方式
  • nginx 配置多 域名 + 多 https
  • Python 反序列化安全问题(二)
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • session共享问题解决方案
  • Swoft 源码剖析 - 代码自动更新机制
  • ubuntu 下nginx安装 并支持https协议
  • uva 10370 Above Average
  • vue数据传递--我有特殊的实现技巧
  • 不上全站https的网站你们就等着被恶心死吧
  • 从伪并行的 Python 多线程说起
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 前端之React实战:创建跨平台的项目架构
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 最简单的无缝轮播
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #前后端分离# 头条发布系统
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • $jQuery 重写Alert样式方法
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (二)换源+apt-get基础配置+搜狗拼音
  • (一一四)第九章编程练习
  • .naturalWidth 和naturalHeight属性,
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET/C# 使用反射注册事件
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .net解析传过来的xml_DOM4J解析XML文件
  • ;号自动换行
  • @column注解_MyBatis注解开发 -MyBatis(15)
  • [2019/05/17]解决springboot测试List接口时JSON传参异常
  • [23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution
  • [C#]winform使用引导APSF和梯度自适应卷积增强夜间雾图像的可见性算法实现夜间雾霾图像的可见度增强