Java中Set接口及其实现

来源:互联网 发布:淘宝时光机 编辑:程序博客网 时间:2024/04/29 07:42
 1.Set接口
  Set是对数学上集的抽象,Set中不包含重复的元素.如何界定是否是重复元素?Set最多可含一个null元素;对于任意的非null元素e1和e2,都满足e1.equals(e2)==false.
  Object.hashcode()的约定:
a.在程序的一次执行中,无论何时在同一个java对象上重复调用hashcode(),都必须一致地返回同一个整数值,并不像Object.equals()那样提供Object是否被修改了的信息,但这个整数值不必在同一个应用程序的多次运行之间保持一致.
b.如果两个Object通过equals()判断是相等的,那么,在这两个Object上调用hashcode()必返回相同的值.
c.如果两个Object通过equals()判断是不相等的,那么,并不要求这两个Object.hashcode()返回不同的整数值.
  集合操作:
   并         s1.addAll()原
   交         s1.retainAll(s2)原
  非对称差    s1.remove(s2)
  对称差      Set symmetricDiff = new HashSet(s1);
              symmertricDiff.add(s2);
              Set tmp = new HashSet(s1);
              tmp.retainAll(s2);
              symmertricDiff.removeAll(tmp);
              则,symmertricDiff即为s1和s2的对称差.
  相对补      Set relativeCompl = new HashSet(s1);
              Set tmp = new HashSet(s1);
              tmp.retainAll(s2);
              relativeCompl.removeAll(tmp);
              则,relativeCompl称为s2的相对补. 
2.Set实现
  HashSet是使用一个哈希表存储元素的,是非排序的,可以随机访问,是Set的最优性能实现.TreeSet实现了SortedSet接口,使用一个红黑树来存储元素,提供了元素的有序存储和访问.
  2.1 HashSet
  HashSet在底层实现上依赖于HashMap.
    HashSet的代码片断:
  // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

    public HashSet() {
 map = new HashMap<E,Object>();
    }

    public boolean add(E o) {
 return map.put(o, PRESENT)==null;
    }

    public boolean remove(Object o) {
 return map.remove(o)==PRESENT;
    }

    public boolean contains(Object o) {
       return map.containsKey(o);
    }
从代码可见,HashSet在底层借用HashMap,使用一个Object类型的哑元值作为HashSet中元素在底层HashMap存储中的映射值.它抓住了HashMap的键不允许重复的特性.对于add()中调用底层映射的put(),将欲添加的元素和一个PRESENT哑元值放入底层map.如果底层Map返回null,说明原来的集合中并不存在该键.对于Map接口的put()返回null时有两种解释,一是原来的Map中不包含该键;另一种可能是原来的Map中已经存储了该健,但该键映射到null.而在HashSet中的add()和remove()等中的返回null只有一种解释,即原来的集合不包含该元素.这是因为HashSet的底层的映射中存储的都是一个名为PRESENT的Object类型的对象,不可能是null.
 
  2.2 TreeSet
   Set接口有一个子接口:SortedSet,提供了集合元素的顺序存储,其中元素保持升序排列.为了在加入一个元素到SortedSet实现时能对这些元素排序,元素类型必须实现Comarable接口,或者建立SortedSet时使用Comparator.否则程序在运行时将抛出ClassCastException.
3.使用Set的注意事项
  如果Set中存储了可变对象,当这些对象出现重复元素,从而从根本上违反了Set的约定,Set的行为也变得不确定.所以,在Set中存储可变对象时,一定要十分小心.同样,对于Map中的key也一样,因为Map中的key也是不允许重复的.
    //DupEleSet.java
  class DupEleSet{
   public static void main(String [] args)
   {
        Calendar cld=new Calendar.getInstance();
       cld.set(2003,0,1);

        Date d1 = cld.getTime();

        cld.set(2005,10,2);
       Date d2 = cld.getTime();

         Set s = new HashSet();
          s.add(d1);
          s.add(d2);

          System.out.println("before modify:"+s);

          d1.setTime(d2.getTime());

            System.out.println("after modified:"+s);

        }
     }
上面的程序输出:
  before modify:[Wed Jan 01 21:54:19 cst 2003,Thu Nov 02 21:54:19 cst 2000]
  after modifyied:[Wed Jan 01 21:54:19 cst 2000,Thu Nov 02 21:54:19 cst 2000]

原创粉丝点击