zoukankan      html  css  js  c++  java
  • Java Set操作

    Set:无顺序,不包含重复的元素

    HashSet:为快速查找设计的Set。存入HashSet的对象必须定义hashCode()。  

    TreeSet: 保存次序的Set, 底层为树结构。使用它可以从Set中提取有序的序列。  

    LinkedHashSet:具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入的次序)。于是在使用迭代器遍历Set时,结果会按元素插入的次序显示。

    HashSet:

    import java.util.HashSet;
    import java.util.Iterator;
    
    public class Main {
        public static void main(String[] args) {
            HashSet set = new HashSet();
            //分别向books集合中添加两个A对象,两个B对象,两个C对象
            set.add(new A());
            set.add(new A());
    
            set.add(new B());
            set.add(new B());
    
            set.add(new C());
            set.add(new C());
            System.out.println(set);
            System.out.println(set.size());
            for(Iterator iter = set.iterator(); iter.hasNext();){
                Object value =  iter.next();
                System.out.println(value);
            }
        }
    }
    
    //类A的equals方法总是返回true,但没有重写其hashCode()方法。不能保证当前对象是HashSet中的唯一对象
    class A
    {
        public boolean equals(Object obj)
        {
            return true;
        }
    }
    
    //类B的hashCode()方法总是返回1,但没有重写其equals()方法。不能保证当前对象是HashSet中的唯一对象
    class B
    {
        public int hashCode()
        {
            return 1;
        }
    }
    
    //类C的hashCode()方法总是返回2,且有重写其equals()方法
    class C
    {
        public int hashCode()
        {
            return 2;
        }
        public boolean equals(Object obj)
        {
            return true;
        }
    }

    Result:

    [com.qhong.B@1, com.qhong.B@1, com.qhong.C@2, com.qhong.A@677327b6, com.qhong.A@1540e19d]
    5
    com.qhong.B@1
    com.qhong.B@1
    com.qhong.C@2
    com.qhong.A@677327b6
    com.qhong.A@1540e19d
    View Code

    B类的hashcode值一样,但是没有定义equals,所以存储了两个对象,但是对象因为hashcode一样,存储位置也一样,两个对象按链表方式存储。

    C类中hashcode值一样,equals也一样,所以只能存储一个值。

    A类中没有定义hashcode,所以存储位置不一样,这里还没有进行equals对比,一样存储两个对象。

    LinkedHashSet

    import java.util.Iterator;
    import java.util.LinkedHashSet;
    
    public class Main {
        public static void main(String[] args) {
            LinkedHashSet books = new LinkedHashSet();
            books.add("Java1");
            books.add("Java2");
            System.out.println(books);
    
            //删除 Java
            books.remove("Java1");
            //重新添加 Java
            books.add("Java1");
            System.out.println(books);
            for(Iterator iter = books.iterator(); iter.hasNext();){
                Object value =  iter.next();
                System.out.println(value);
            }
        }
    }

    Result:

    [Java1, Java2]
    [Java2, Java1]
    Java2
    Java1
    View Code

    元素的顺序总是与添加顺序一致,LinkedHashSetTest是HashSet的子类,因此它不允许集合元素重复.

    TreeSet:

    import java.util.TreeSet;
    
    public class Main {
        public static void main(String[] args) {
            TreeSet nums = new TreeSet();
            //向TreeSet中添加四个Integer对象
            nums.add(5);
            nums.add(2);
            nums.add(10);
            nums.add(-9);
    
            //输出集合元素,看到集合元素已经处于排序状态
            System.out.println(nums);
    
            //输出集合里的第一个元素
            System.out.println(nums.first());
    
            //输出集合里的最后一个元素
            System.out.println(nums.last());
    
            //返回小于4的子集,不包含4
            System.out.println(nums.headSet(4));
    
            //返回大于5的子集,如果Set中包含5,子集中还包含5
            System.out.println(nums.tailSet(5));
    
            //返回大于等于-3,小于4的子集。
            System.out.println(nums.subSet(-3 , 4));
        }
    }

    Result:

    [-9, 2, 5, 10]
    -9
    10
    [-9, 2]
    [5, 10]
    [2]
    View Code

    与HashSet集合采用hash算法来决定元素的存储位置不同,TreeSet采用红黑树的数据结构来存储集合元素。

    TreeSet支持两种排序方式: 自然排序、定制排序

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

    通过ComparaTor接口可以实现定制排序。

    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.TreeSet;
    
    public class Main {
        public static void main(String[] args) {
            TreeSet ts = new TreeSet(new Comparator()
            {
                //根据M对象的age属性来决定大小
                public int compare(Object o1, Object o2)
                {
                    M m1 = (M)o1;
                    M m2 = (M)o2;
                    return m1.age > m2.age ? -1 : m1.age < m2.age ? 1 : 0;
                }
            });
            ts.add(new M(5));
            ts.add(new M(-3));
            ts.add(new M(9));
            System.out.println(ts);
            for(Iterator iter = ts.iterator(); iter.hasNext();){
                Object value =  iter.next();
                System.out.println(value);
            }
        }
    }
    class M
    {
        int age;
        public M(int age)
        {
            this.age = age;
        }
        public String toString()
        {
            return "M[age:" + age + "]";
        }
    }

    Result:

    [M[age:9], M[age:5], M[age:-3]]
    M[age:9]
    M[age:5]
    M[age:-3]
    View Code

    EnumSet:

    import java.util.EnumSet;
    
    public class Main {
        public static void main(String[] args) {
            //创建一个EnumSet集合,集合元素就是Season枚举类的全部枚举值
            EnumSet es1 = EnumSet.allOf(Season.class);
            //输出[SPRING,SUMMER,FALL,WINTER]
            System.out.println(es1);
    
            //创建一个EnumSet空集合,指定其集合元素是Season类的枚举值。
            EnumSet es2 = EnumSet.noneOf(Season.class);
            //输出[]
            System.out.println(es2);
            //手动添加两个元素
            es2.add(Season.WINTER);
            es2.add(Season.SPRING);
            //输出[SPRING,WINTER]
            System.out.println(es2);
    
            //以指定枚举值创建EnumSet集合
            EnumSet es3 = EnumSet.of(Season.SUMMER , Season.WINTER);
            //输出[SUMMER,WINTER]
            System.out.println(es3);
    
            EnumSet es4 = EnumSet.range(Season.SUMMER , Season.WINTER);
            //输出[SUMMER,FALL,WINTER]
            System.out.println(es4);
    
            //新创建的EnumSet集合的元素和es4集合的元素有相同类型,
            //es5的集合元素 + es4集合元素 = Season枚举类的全部枚举值
            EnumSet es5 = EnumSet.complementOf(es4);
            //输出[SPRING]
            System.out.println(es5);
        }
    }
    enum Season
    {
        SPRING,SUMMER,FALL,WINTER
    }

    Result:

    [SPRING, SUMMER, FALL, WINTER]
    []
    [SPRING, WINTER]
    [SUMMER, WINTER]
    [SUMMER, FALL, WINTER]
    [SPRING]
    View Code

    Set集合类应用场景:

    1) HashSet的性能总是比TreeSet好(特别是最常用的添加、查询元素等操作),因为TreeSet需要额外的红黑树算法来维护集合元素的次序。只有当需要一个保持排序的Set时,才应该使用TreeSet,否则都应该使用HashSet
    2) 对于普通的插入、删除操作,LinkedHashSet比HashSet要略慢一点,这是由维护链表所带来的开销造成的。不过,因为有了链表的存在,遍历LinkedHashSet会更快
    3) EnumSet是所有Set实现类中性能最好的,但它只能保存同一个枚举类的枚举值作为集合元素
    4) HashSet、TreeSet、EnumSet都是"线程不安全"的,通常可以通过Collections工具类的synchronizedSortedSet方法来"包装"该Set集合。
    SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));

    http://www.cnblogs.com/LittleHann/p/3690187.html

  • 相关阅读:
    数据库01
    并发编程6
    并发编程5
    并发编程4
    并发编程3
    并发编程2
    并发编程1
    kali 下文件操作
    kali driftnet
    2017.1.1
  • 原文地址:https://www.cnblogs.com/hongdada/p/6049895.html
Copyright © 2011-2022 走看看