您的位置:首页 > 其它

HashMap and HashSet

2013-07-31 19:33 323 查看
HashMap和HashSet

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

虽然集合号称存储的是Java对象,但实际上并不会真正将Java对象放入Set集合中,而只是在Set集合中保留这些对象的引用而已。也就是说,Java集合实际上是多个引用变量所组成的集合,这些引用变量指向实际的Java对象。

import java.util.ArrayList;

import java.util.List;

 

class Apple{

      doubleweight;

      public Apple(double weight){

            this.weight = weight;

      }

}

publicclass ListTest {

    publicstaticvoid main(String[] args){

      Apple t1 = new Apple(2.2);

      Apple t2 =new Apple(1.8);

      List<Apple> list = new ArrayList<Apple>(4);

      list.add(t1);

      list.add(t2);

      System.out.println(list.get(0)==t1);

      System.out.println(list.get(1)==t2);

    }

}

Output:

true

true

 

ArrayList底层是基于数组实现的,也就是说ArrayList底层封装的是数组,每次创建时传入的int参数就是它包装的数组的长度;

对于HashMap而言,它的存储方式要比ArrayList复杂一些,采用所谓的”Hash算法”来决定每个元素的存储位置。

当执行程序map.put(“yuwen”,80.0)时,系统将调用”yuwen”的hashcode()方法得到其hashcode值――每个Java对象都有hashcode()方法,都可通过该方法获得它的hashcode的值。得到这个值后,系统会根据该hashcode值来决定该元素的存储位置。

HashMap在底层将key-value当成一个整体进行处理,这个整体就是一个Entry对象。HashMap底层采用一个Entry[]数组来保存所有的key-value对,当需要存储一个Entry对象时,会根据Hash算法来决定其存储位置;当需要取出一个Entry时,也会根据Hash算法找到其存储位置,直接取出该Entry。由此可见,HashMap之所以能快速存,取它所包含的Entry,完全类似于生活中,不同的东西要放在不同的位置,需要时才能快速找到它。

当创建HashMap时,有一个默认的负载因子(load factor),其默认值为0.75.增大负载因子可以减少Hash表(就是那个Entry数组)所占用的内存空间,但会增加查询数据的时间开销,而查询是最频繁的操作(HashMap的get()与put()方法都要用到查询);减小负载因子会提高数据查询的功能,但会降低Hash表所占用的内存空间。

如果开始就知道HashMap会保存多个key-value对,可以在创建时就使用较大的初始化容器,如果Entry的数量一直不会超过极限容量(capacity*load
factor),HashMap就无需调用resize()方法重新分配table数组,从而保证较好的性能。当然,开始就将初始容量设置太高可能会浪费空间(系统需要创建一个长度为capacity的Entry数组),因此创建HashMap时初始化容量设置也需要小心对待。对于HashSet而言,它是基于HashMap实现的。HashSet底层采用HashMap来保存所有元素。

import java.util.HashSet;

import java.util.Set;

 

class Name{

      private Stringfirst;

      private Stringlast;

      public Name(String first,String last){

            this.first = first;

            this.last = last;

      }

      publicboolean equals(Object o){

            if(this == o){

                  returntrue;

            }

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

                  Name n = (Name)o;

                  return n.first.equals(first)
&& n.last.equals(last);

            }

            returnfalse;

      }

}

 

publicclass HashSetTest {

    publicstaticvoid main(String[] args){

      Set<Name> s = new HashSet<Name>();

      s.add(new Name("abc","123"));

      System.out.println(s.contains(new Name("abc","123")));

    }

}

Output:

False

输出false的原因是因为HashSet判断两个对象相等的标准除了要求通过equals()方法比较返回的true之外,还要求两个对象的hashCode()返回值相等,上面的程序没有重写hashCode()方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  HashMap和HashSet