zoukankan      html  css  js  c++  java
  • 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节点中储存键值对对象。
     
     
     
    参考:
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    【已解决】github中git push origin master出错:error: failed to push some refs to
    好记心不如烂笔头,ssh登录 The authenticity of host 192.168.0.xxx can't be established. 的问题
    THINKPHP 5.0目录结构
    thinkphp5.0入口文件
    thinkphp5.0 生命周期
    thinkphp5.0 架构
    Django template
    Django queryset
    Django model
    Python unittest
  • 原文地址:https://www.cnblogs.com/wanglao/p/5329438.html
Copyright © 2011-2022 走看看