zoukankan      html  css  js  c++  java
  • 《疯狂Java讲义精粹》读书笔记12 Set集合(一)

    ===============《疯狂Java讲义精粹》读书笔记12 ------  Set集合========================

      Set集合里多个对象之间没有明显的顺序,Set集合不允许包含相同的元素,如果add相同的元素就会返回false,新元素不会被加入。

    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * Set里面不允许重复添加相同的对象
     * @author <<疯狂Java讲义精粹>>
     *
     */
    public class TestSet {
        public static void main(String[] args) {
            Set name = new HashSet();
            name.add("CocoonFan");
            if(name.add(new String("CocoonFan"))){
                System.out.println("添加成功!");
            } else {
                System.out.println("添加失败!\n当前的name的内容是:" + name);
            }
        }
    }

     输出的结果为:

    添加失败!
    当前的name的内容是:[CocoonFan]

      很明显前后两次添加的字符串对象不是同一个对象,但是Set不会同时接受这两个对象。因为Set判断两个对象相同不是用==运算符,而是根据equals方法。

    一、HashSet类                                                                                          

      HashSet是Set接口的典型实现,HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。

      它具有如下特点:

        · 不能保证元素的排列顺序,顺序可能发生变化
        · HashSet不是同步的
        · 集合的元素值可以为null
        · HashSet判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回的值也相等

      下面的程序提供了A、B、C三个类分别重写了equals()、hashCode()两个方法或者全部:

    import java.util.HashSet;
    
    /**
     * class A 重写了equals()方法始终返回true
     *
     */
    class A{
        public boolean equals(Object obj){
            return true;
        }
    }
    
    /**
     * class B 重写了hashCode()方法,始终返回1.
     *
     */
    class B{
        public int hashCode() {
            return 1;
        }
    }
    
    /**
     * class C 重写了hashCode()方法(始终返回2),且重写了equals()方法
     *
     */
    class C {
        public int hashCode() {
            return 2;
        }
        
        public boolean equals(Object obj) {
            return true;
        }
    }
    
    public class TestEqualsHashCode {
        public static void main(String[] args) {
            HashSet name = new HashSet();
            name.add(new A());
            name.add(new A());
            
            name.add(new B());
            name.add(new B());
            
            name.add(new C());
            name.add(new C());
            
            System.out.println(name);
        }
    }

    输出结果:

    [B@1, B@1, C@2, A@4f1d0d, A@18a992f]

      从结果可以看出:
        · HashSet 里面装的元素顺序是不确定的
        · 集合里面只添加了两个A,两个B,一个C,说明Set判断两个对象的标准是equalse()方法和hashCode()方法都要一致

      重写hashCode方法时应注意;
        · 在程序运行中,同一个对象多次调用hashCode(0方法应该返回相同的值
        · 当两个对象通过equals方法比较返回true 的时候,这两个对象的hashCode()的返回值也应该相等

    二、LinkedHashSet类                                                                                   

      HashSet还有一个子类LinkedHashSet,它也是根据元素的hashCode值来决定元素的储存位置,但是它同时还使用链表维护元素的秩序。它比较适合迭代访问元素。
      输出元素的顺序和添加元素的顺序一致。

    三、TreeSet类                                                                                         

      TreeSet类是SortedSet几口的实现类,它可以确保元素处于排序状态,与HashSet相比TreeSet提供了几个额外的方法:
        · Comparator comparator(): 如果TreeSet采用了定制排序,该方法返回定制排序所使用的Comparator;如果采用了自然排序则返回null
        · Object last():返回集合中的最后一个元素
        · Object first(): 返回集合中的第一个元素
        · Object lower(Object e):返回集合中位于指定元素之前的元素(参考元素不需要是TreeSet中的元素)
        · Object higher(Object e):返回集合中位于指定元素之后的元素(参考元素不需要是TreeSet中的元素)
        · SortedSet subSet(fromElement, toElement):返回Set的子集合,范围 [fromElement, toElement)
        · SortedSet headSet(toElement):返回Set的子集合,范围从开头到toElement
        · SortedSet tailSet(fromElement):返回Set的子集合,由大于会等于fromElement的元素组成

      下面是一个测试的例子

     1 import java.util.TreeSet;
     2 
     3 
     4 public class TestTreeSet {
     5     public static void main(String[] args) {
     6         TreeSet numbers = new TreeSet();
     7         numbers.add(5);
     8         numbers.add(2);
     9         numbers.add(-9);
    10         numbers.add(10);
    11         numbers.add(-20);
    12         
    13         //输出元素,将会看到集合已经被处于排序状态
    14         System.out.println(numbers);
    15         
    16         //输出第一个元素
    17         System.out.println("集合的第一个元素是:" + numbers.first());
    18         
    19         //输出集合里的最后一个元素
    20         System.out.println("集合里的最后一个元素是: " + numbers.last());
    21         
    22         //返回小于4(不包含) 的自子集,注意4并没有在集合中
    23         System.out.println("小于4的自己是:" + numbers.headSet(4));
    24         
    25         //返回大于或等于5的子集
    26         System.out.println("大于等于5的子集是:" + numbers.tailSet(5));
    27         
    28         //截取一个子集[A,B)
    29         System.out.println("在[2,100)之间的子集是:" + numbers.subSet(2, 100));    
    30     }
    31 }

    输出的结果为:

    [-20, -9, 2, 5, 10]
    集合的第一个元素是:-20
    集合里的最后一个元素是: 10
    小于4的自己是:[-20, -9, 2]
    大于等于5的子集是:[5, 10]
    在[2,100)之间的子集是:[2, 5, 10]

      TreeSet支持两种排序方法:自然排序和定制排序

    (一)、自然排序

      TreeSet会调用compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按照升序排列,这种方式就是自然排序。

      Java提供了Comparable接口,当两个对象相比较的时候就会调用该接口的compareTo(Object obj)方法,相等返回0,大于返回一个正整数,小于返回一个负整数。

      下面是实现了Comparable就扣的常用类:
        · BigDecimal、BigInteger以及所有的整数值类型对应的包装类:按他们的数值大小进行比较
        · Character: 按字符的UNICODE值进行比较
        · Boolean:true对应的包装类实例大于false
        · String :按字符集中的UNICODE值进行比较
        · Date、Time:后面的时间、日期比前面的时间日期大

      如果试图把一个对象添加到TreeSet中去,则该对象必须实现Comparable接口,否则程序将跑出异常。(只有第一个元素无需实现Comparable接口,但是取出的时候还是会跑出ClassCastException异常)。在实现compareTo(Object obj)方法时必须将比较的对象强制转换成相同类型。

      当向TreeSet中添加多个不同的不同类型的对象的时候必须自己自己实现Comparable接口。例如先向TreeSet中添加一个字符串,再添加一个Data类型的元素的时候就会跑出异常。

      如果两个对象通过equals()方法返回true的时候,这两个对象通过compareTo(Object obj)方法比较应该返回0,否则会很麻烦,因为compareTo(Object obj)比较相等时,TreeSet不会让地儿个元素加进去,这是就会与Set集合的规则(不能有重复的元素)相冲突。

      有时候会有这样的问题,修改TreeSet中对象的成员变量之后可能与集合中的其他元素相等,这不久与Set集合的规则矛盾了吗?这时候该怎么处理呢?

  • 相关阅读:
    java 基础7
    java 基础5
    java 基础6
    java 基础4
    java 基础2
    java 基础3
    java 基础1
    使用HTML的基本结构创建网页
    jsp Servlet 文件上传
    Filter过滤器 不登陆无法访问其他页面
  • 原文地址:https://www.cnblogs.com/CocoonFan/p/2954090.html
Copyright © 2011-2022 走看看