• HashMap 和 HashSet


    对于HashSet而言,系统采用Hash算法决定集合元素的存储位置,这样可以保证快速存取集合元素;

    对于HashMap,系统将value当成key的附属,系统根据Hash算法来决定key的存储位置,这样可以保证快速存取集合key,而value总是紧随key存储。

    (这些集合虽然号称存储的是java对象,但实际上并不会真正将java对象放入set集合中,而只是在Set集合中保留这些对象的引用。

    当程序视图将多个key-value 放入HashMap中时,采用一种“Hash算法”来决定每个元素的存储位置。

     1 public V put(K key, V value)
     2 {
     3     if(key == null)
     4             return putForNullKey(value);
     5     int hash = hash(key.hashCode());
     6     
     7     int i = indexFor(hash, table.length);
     8 
     9     for(Entry<K,V> e = table[i]; e!=null;e=e.next)
    10     {
    11             Object K;
    12             if(e.hash==hash && ((k=e.key) == k || key.equals(k))
    13             {
    14                 V oldValue = e.value;
    15                 e.value= value;
    16                 e.recordAccess(this);
    17                 return oldValue;
    18               }
    19     }
    20         modCount ++;
    21     addEnrty(hash,key,value,i);
    22     return null;
    23 }
    View Code

    一个重要的内部接口Map.Entry,每个Map.Entry其实就是一个Key-Value对。当系统决定存储HashMap中的key-value对是,只是根据key来计算并决定每个Entry的存储位置:如果两个Entry的key的hashCode()返回值相同,那么它们的存储位置相同;如果这两个key通过equals比较返回true,新添加的Entry的value将覆盖原有Entry的value,但key不会覆盖;如果这两个key通过equals比较返回false,新添加的Entry将与集合中原有Entry形成Entry链。见addEntry()方法:

    1 void addEntry(int hash,K key,V value,int bucketIndex)
    2 {
    3     Entry<K,V> e = table[bucketIndex];
    4     table[bucketIndex] = new Entry<K,V>(hash,key,value,e);
    5     if(size++ >= threshold)  //threshold包含HashMap能容纳的key-value对的极限。
    6         resize(2*table.length);
    7 }
    View Code

    table实质就是一个普通数组,每个数组都有一个固定一的长度,这个数组的长度就是HashMap的容量。

    HashSet是基于HashMap实现的,HashSet底层采用HashMap来保存所有元素。

     1 class Name
     2 {
     3     private String first;
     4     private String last;
     5     public Name(String first, String last)
     6     {
     7         this.first = first;
     8         this.last  = last;
     9     }
    10     public boolean equals(Object o)
    11     {
    12         if(this == o)
    13             return true;
    14         if(o.getClass() == Name.class)
    15         {
    16             Name n =(Name) o;
    17             return n.first.equals(first) && n.last.equals(last);
    18         }
    19         return false;
    20     }
    21     
    22     public class HashSetTest
    23     {
    24         public static void main(String[] args)
    25         {
    26             Set<Name> s = new HashSet<Name>();
    27             s.add(new Name("abc","123"));
    28             System.out.println(s.contains(new Name("abc","123");
    29         }
    30     }
    31     
    View Code

    运行结果是false. 

    因为HashSet判断两个对象相等的标准除了要求通过equals方法比较返回true外,还要求两个对象的hashCode()返回值相等。

    重写hashCode()方法:

    public int hashCode()

    {

        return first.hashCode();

    }

    public boolean equals(Object o)

    {

      ....

      if(o.getClass() == Name.class)

      {

        Name n = (Name) o;

        return n.first.equals(first);

      }

      ...

    }

  • 相关阅读:
    未来超市 轻松之旅
    超市淡季从竞争对手抓起
    如何监管超市收银漏洞
    一份好的方案需要注意哪些内容?
    超市负库存产生的原因及对策
    成功演示的关键步骤(三)
    成功演示的关键步骤(一)
    js iframe 地址
    js 弹出可拖动窗口
    js 关闭当前页面不提示
  • 原文地址:https://www.cnblogs.com/happinessqi/p/3440233.html
Copyright © 2020-2023  润新知