• Dictionary(HashMap)的实现


     什么是哈希表?

      哈希表(Hash table,也叫散列表),是根据key而直接进行访问的数据结构。也就是说,它通过把key映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
     
    为什么要了解字典类?
     
    1.HashMap的性能最棒查找,添加,删除的时间复杂度都是常数。

    Data Structure

    Add

    Find

    Delete

    GetByIndex

     Array (T[])

    O(n)

    O(n)

    O(n)

    O(1)

     Linked list (LinkedList<T>)

    O(1)

    O(n)

    O(n)

    O(n)

     Resizable array list (List<T>)

    O(1)

    O(n)

    O(n)

    O(1)

     Stack (Stack<T>)

    O(1)

    -

    O(1)

    -

     Queue (Queue<T>)

    O(1)

    -

    O(1)

    -

     Hash table (Dictionary<K,T>)

    O(1)

    O(1)

    O(1)

    -

     Tree-based dictionary

     (SortedDictionary<K,T>)

      O(log n)  

      O(log n)  

      O(log n)  

    -

     Hash table based set

     (HashSet<T>)

    O(1)

    O(1)

    O(1)

    -

     Tree based set

     (SortedSet<T>)

    O(log n)

    O(log n)

    O(log n)

    -

     
     
    2.举一反三。HashSet是基于HashMap来实现的,操作很简单,更像是对HashMap做了一次“封装”,而且只使用了HashMap的key来实现各种特性()
     
    HashMap的原理?
     

      哈希表的做法其实很简单,就是把key通过一个固定的算法函数即所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。

        而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位
    put方法:
    
    
    public V put(K key, V value) {
    // 处理key为null,HashMap允许key和value为null
    if (key == null)
    return putForNullKey(value);
    // 得到key的哈希码
    int hash = hash(key);
    // 通过哈希码计算出bucketIndex
    int i = indexFor(hash, table.length);
    // 取出bucketIndex位置上的元素,并循环单链表,判断key是否已存在
    for (Entry<K,V> e = table[i]; e != null; e = e.next) {
    Object k;
    // 哈希码相同并且对象相同时
    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
    // 新值替换旧值,并返回旧值
    V oldValue = e.value;
    e.value = value;
    e.recordAccess(this);
    return oldValue;
    }
    }
     
    // key不存在时,加入新元素
    modCount++;
    addEntry(hash, key, value, i);
    return null;
    }
     
     数组的特点是:寻址容易,插入和删除困难;而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为“链表的数组”。
     
    与其他集合的比较:
    1.特点比较:

    有序否

    允许元素重复否

    Collection

    List

    Set

    AbstractSet

    HashSet

    TreeSet

    是(用二叉树排序)

    Map

    AbstractMap

    使用key-value来映射和存储数据,Key必须惟一,value可以重复

    HashMap

    TreeMap

    是(用二叉树排序)

    2.HashMap与Hashtable的区别:
    HashMap是非synchronized,而Hashtable是synchronized(针对整张表的锁,性能不佳),HashMap可以 可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
    3.由于HashMap不是线程安全的,在多线程环境中使用 ConcurrentHashMap。原因:其关键在于使用了锁分离技术, ConcurrentHashMap使用锁桶,默认将hash表分为16分桶,线程操作时锁定一个桶,这样,最多可以16个线程同时写入。大大提升并发性。而读方面,ConcurrentHashMap使用弱一致迭代器,当iterator被创建后数据改变时创新新的数据,完成后再将头指针替换为新数据。这保证了写的连续性和扩展性。
     
    操作:
    遍历:
    Map map = new HashMap();
      Iterator iter = map.entrySet().iterator();
      while (iter.hasNext()) {
      Map.Entry entry = (Map.Entry) iter.next();
      Object key = entry.getKey();
      Object val = entry.getValue();
      }
     
    删除:
    我们可以发现Dictionary在添加,删除元素按照如下方法进行:
    通过Hash算法来计算到指定的Bucket上,碰撞到同一个Bucket槽上所有数据形成一个单链表
    默认情况Entries槽中的数据按照添加顺序排列
    删除的数据会形成一个 LinkedList的链表,添加数据的时候,优先向 LinkedList链表中添加数据, LinkedList为空则按照count依次排列。  HashMap在每个LinkedList节点中储存键值对对象。
     
     
     
    参考:
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    【2】Java包装类
    【1】Java异常
    【10】Java多态:内部类
    【9】Java多态:接口
    【8】Java多态:抽象类(abstract关键字)
    【7】Java多态:向上转型、向下转型、instanceof运算符
    【6】Java单例模式
    元素定位工具:Chrome浏览器ChroPath插件
    linux添加环境变量
    php导出数据到多个csv并打包压缩
  • 原文地址:https://www.cnblogs.com/wanglao/p/5329438.html
Copyright © 2020-2023  润新知