java base Set集合

  • Set 无序,不重复
    • HashSet 无序的Set
      • LinkedHashSet 有序的(添加顺序)
    • SortedSet //接口,抽象出TreeSet可以公用的部分
      • TreeSet 可以排序的Set
    • EnumSet 专为Enum类定义的集合

Set集合

  1. 概述:无序集合,不可重复(某些子容器支持排序)
  2. HashSet是Set的典型接口的实现,
    • 按hash值储存集合
    • 具有很好的存储型以及查找性
    • 无序的,可能与添加顺序不同
    • 不是同步的,多线程,必须通过代码来保证同步
    • 集合元素可以是null
    • 如果hashset中存在可变元素,元素一旦被修改将无法删除,就算删除全部的未修改元素在删除已修改元素也无法删除

    package java集合;
    import java.util.HashSet;
    import java.util.Iterator;

    class R{
        int count;
        public R(int count){
            this.count = count;
        }

        @Override
        public String toString() {
            return "count:"+count+"\t";
        }

        @Override 重写equals方法,通过判断count确定对象是   否重复
        public boolean equals(Object obj) {
            if (this==obj){
                return true;
            }else if (obj!=null&&obj.getClass() ==R.class){
                R a = (R)obj;
                return this.count == a.count;
            }
            return false;
        }

        @Override
        public int hashCode() {
            return this.count;
        }
    }
    public class HashSetTest02 {
        public static void main(String[] args){
            HashSet hs = new HashSet();
            hs.add(new R(55));
            hs.add(new R(12));
            hs.add(new R(32));
            hs.add(new R(-1));
            System.out.println(hs);
            Iterator it = hs.iterator();
            R first = (R)it.next();
            first.count = 12;
            System.out.println(hs);
            hs.remove(new R(12));//移除成功
    //        hs.remove(new R(12));//第二次失败
            System.out.println(hs.contains(new R(12))); //不包含r12
    //        hs.remove(new R(32));  //尝试删除被改之前 的对象,删除失败
            System.out.println(hs);//修改之后的对象,无 法删除
            hs.remove(first);
            System.out.println(hs);//尝试删除元素修改前 的引用对象,修改失败

        }
    }

注意:hashSet判断两个元素是否相同是通过hashCode和equals来判断的
3. linkerHashSet
* 他是hashSet的子类,它是有序的,顺序按照加入的先后顺序


    package java集合;
    import java.util.Iterator;
    import java.util.LinkedHashSet;

    public class LinkedHashSetTest {

        //linkhashset是hashSetd的子类
        //相比hashset,他是有序的,会按照元素的插入顺序保   存
        //性能略微低于hashset,因为要用链表来维持顺序,
        // 但是如果迭代访问set里的全部的元素时,性能还是不  错的,因为链表来维护内部的顺序
        public static void main(String[] args){
            LinkedHashSet linkedHashSet = new   LinkedHashSet();
            linkedHashSet.add("java");
            linkedHashSet.add("python");
            Iterator iterator = linkedHashSet.iterator  ();
            iterator.forEachRemaining   (obj->System.out.println("迭代集合"+obj));
            linkedHashSet.remove("java");
            linkedHashSet.add("java");
            Iterator iterator1 = linkedHashSet.iterator ();
            iterator1.forEachRemaining  (obj->System.out.println("迭代集合"+obj));
        }
    }

  1. SortedSet --> TreeSet
    • 这是一个可以排序的Set,但是他们的元素必须实现Comparable接口(绝大多的基础类型的包装类都实现了)
    • 提供自然排序和定制排序(自然排序无法满足某些特定的需求)
    package java集合;

    import java.util.Iterator;
    import java.util.TreeSet;

    class TreeA implements Comparable{
        /*
        TreeSet中被改变了的元素是无法移除的
        本身没有被改变,但是与改变了之后的元素相同的元素是  可以移除的
         */
        int count;
        public TreeA(int count){
            this.count = count;
        }
        public int compareTo(Object obj){
            return this.count>((TreeA)obj).count?1: (this.count<((TreeA)obj).count?-1:0);
        }
    }
    public class TreeSetTest03 {
        public static void main(String[] args){
            TreeSet ts = new TreeSet();
    //        TreeA a = new TreeA(2);
            ts.add(new TreeA(5));
            ts.add(new TreeA(9));
            ts.add(new TreeA(4));
            ts.add(new TreeA(2));
            ts.add(new TreeA(100));
            System.out.println(ts.size());
            ts.iterator().forEachRemaining  (obj->System.err.println(((TreeA)obj) .count));
            TreeA ta = (TreeA) ts.last();
            ta.count = 5;
            ts.iterator().forEachRemaining  (obj->System.out.println(((TreeA)obj) .count));
            //删
            System.out.println(ts.remove(new TreeA(5))) ;
            ts.iterator().forEachRemaining  (obj->System.out.println(((TreeA)obj) .count));
            ts.remove(new TreeA(2));
            ts.remove(new TreeA(4));
            ts.remove(new TreeA(9));
            ts.iterator().forEachRemaining  (obj->System.err.println(((TreeA)obj) .count));
            //将所有可删除的元素删除之后就能修改那些被改变  之后的元素了
            System.out.println(ts.remove(new TreeA(5))) ;
        }
    }

//定制排序,需要在创建TreeSet容器的时候,参数传入定制的方法,一个Compartor的对象作为参数

    package java集合;

    import java.util.Comparator;
    import java.util.TreeSet;

    class Prople{
        int age;
        public Prople(int age){
            this.age = age;
        }

        @Override
        public String toString() {
            return "age:"+age;
        }
    }
    public class TreeSetTest04 {
        //Tree的定制排序
        public static void main(String[] args){
            TreeSet ts = new TreeSet(new Comparator() {
                @Override
                public int compare(Object o, Object t1)  {
                    return ((Prople)o).age>((Prople)t1) .age?-1:((Prople)o)
                            .age<((Prople)t1).age?1:0;
                }
            });
            ts.add(new Prople(1));
            ts.add(new Prople(2));
            ts.add(new Prople(4));
            ts.add(new Prople(3));
            System.out.println(ts);
        }
    }
  1. EnumSet
    • 这是一个特意为枚举类制定的集合,这个集合只能容纳枚举类的元素,并且,这些枚举类的元素还必须是同一枚举类的元素
    • 这个集合在创建时就需要指定,创建容易的枚举类型(或者用一个装满枚举元素的Collection类型的集合来创建EnumSet)
    • 这个集合特有的方法基本就是以各种各样的姿势创建对象
    //创建对象的方法大多差距甚微,这里列出几个代表性的
    package java集合;
    
    import java.util.EnumSet;
    
    enum Season{
        SPRING,SUMMER,FALL,WINTER;
    }
    public class EnumSetTest {
        public static void main(String[] args){
            //创建一个Season枚举类型的EnumSet
            EnumSet es = EnumSet.noneOf(Season.class);
            es.add(Season.FALL);
            es.add(Season.SPRING);
            es.add(Season.SUMMER);
            System.out.println(es);
            //[SPRING, SUMMER, FALL]
            //创建一个包含指定枚举类的所有元素(Season)的  enumset
            EnumSet es1 = EnumSet.allOf(Season.class);
            System.err.println(es1);
            //[SPRING, SUMMER, FALL, WINTER]
            
            //创建一个包含从a到b的范围内的所有枚举值
            EnumSet es2 = EnumSet.range(Season.SPRING,  Season.FALL);
            System.out.println(es2);
            //[SPRING, SUMMER, FALL]
        }
    }

总结:

hashSet的性能比TreeSet的略强,TreeSet需要额外的红黑算法来维护集合元素的次序,需要一个保持排序的用TreeSet否则用hashSet

linkedHashSet,插入和删除相比hashSet会有点慢,因为要花费开销来维护链表,但是如果遍历的话,linkdHashSet会更快

EnumSet性能最好但是限制过大

声明:这些方法全部都是线程不安全的,如若有需要,可以通过Collections工具类中的方法进行包装。
posted @ 2019-08-17 23:18  zlisang  阅读(154)  评论(0)    收藏  举报