Set集合类

HashSet

HashSet 是按照Hash算法来存储集合里的元素,具有良好的存储和查找功能。
HashSet有以下特点:

  • 不能保证元素的排列顺序,顺序有可能发生变化。
  • 集合元素值是可以为NULL的。
  • HashSet不是同步的,如果多个线程同时访问HashSet集合,且同时有多条线程修改HashSet集合时,必须通过代码保证同步

HashCode值有点类似于数组的索引值
HashSet集合判断两个元素相等的标准是两个对象equals方法返回true,并且两个对象的hashCode()方法返回值也相等

class A {
    public boolean equals(Object obj)
    {
        return true;
    }
}

class B{
    public int hashCode(){
        return 1;
    }
}

class C{
    public boolean equals(Object obj)
    {
        return true;
    }
    public int hashCode(){
        return 2;
    }
}


public class T4 {

    public static void main(String[] args) {
        HashSet books = new HashSet();
        books.add(new A());
        books.add(new A());
        books.add(new B());
        books.add(new B());
        books.add(new C());
        books.add(new C());
        System.out.println(books);
    }
}

结果为:[Test.B@1, Test.B@1, Test.C@2, Test.A@74a14482, Test.A@4554617c] C类只有一个

LinkedHashSet

也是根据元素hashCode值来决定元素的位置,同时使用链表维护元素的次序,遍历时会按照添加顺序来。

   public static void main(String[] args) {
        LinkedHashSet c = new LinkedHashSet();
        c.add("我爱你");
        c.add("奇松巴");
        c.add("JJ");
        c.remove("奇松巴");
        c.add("奇松巴");
System.out.println(c);
    }
//输出结果:[我爱你, JJ, 奇松巴] 先进排前面

TreeSet

是SortedSet接口的唯一实现,可确保集合的元素处于排序状态,在前面的HashSet集合相比,TreeSet有额外的方法提供:

  • Comparator comparator():返回当前Set使用的Comparator,或者返回null,表示自然排序
  • Object first():返回集合中的第一个元素。
  • Object first():返回集合中的最后一个元素。
  • Object lower(Object e):返回集合中位于指定元素之前的元素(即小于指定元素的最大元素,参考元素不需要是TreeSet的元素)
  • Object higher(Object e):返回集合中位于指定元素之后的元素(即大于指定元素的最小元素,参考元素不需要是TreeSet的元素)
  • SortedSet subSet(fromElement,toElement):返回此Set的子集合,范围从fromElemnt(包含)到toElement(不包含)
  • SortedSet headSet(toElement):返回Set的子集,由小于toElement的元素组成
  • SortedSet tailSet tailSet(fromElement):返回此Set的子集,由大于或等于fromElement的元素组成.
    public static void main(String[] args) {
        TreeSet nums = new TreeSet();
        nums.add(5);
        nums.add(2);
        nums.add(10);
        nums.add(-9);
        System.out.println(nums);
//        结果[-9, 2, 5, 10]
        System.out.println(nums.first());
        System.out.println(nums.last());
        System.out.println(nums.headSet(4));
        System.out.println(nums.tailSet(5));
        System.out.println(nums.subSet(-3,4));
//-9
//10
//[-9, 2]
//[5, 10]
//[2]
    }

TreeSet采用的是红黑树的数据结构对元素进行排序,支持两种排序方式,默认情况下是自然排序。

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

public class T7 {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet();
        ts.add(new Err());
        ts.add(new Err());
    }


}

Exception in thread “main” java.lang.ClassCastException: Test.Err cannot be cast to java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1294)
at java.util.TreeMap.put(TreeMap.java:538)
at java.util.TreeSet.add(TreeSet.java:255)
at Test.T7.main(T7.java:9)

向TreeSet集合中添加元素时,只有第一个元素可以无须实现Comparable接口,后面添加的所有元素都必须实现Comparable接口,当然这也不是一种好做法,当试图从TreeSet中取出元素时,依然会引发异常

注意:大部分类在实现compareTo方法时,都需将被比较的类型转换为相同类型,因为同类才能比较大小,所以集合中其他元素与该元素应是同一类的实例。否在会引发异常。

定制排序
由自己来定制排序的规律逻辑,例如降序排序,实现定制排序需要在创建TreeSet集合对象时提供一个Comparator对象与该TreeSet集合关联,由Compatator对象负责集合元素的排序逻辑。

class M{
    int age;
    public M(int age)
    {
        this.age = age;
    }
    public String toString(){
        return "M对象(age:"+age+")";
    }
}

public class A1 {
    public static void main(String[] args) {
        TreeSet ts = new TreeSet(new Comparator() {

            public int compare(Object o1, Object o2) {
                M m1 = (M) o1;
                M m2 = (M) o2;
                if (m1.age>m2.age)
                {
                    return -1;
                }
                else if (m1.age == m2.age)
                {
                    return 0;
                }
                else
                {
                    return 1;
                }

            }
        });
        ts.add(new M(5));
        ts.add(new M(-3));
        ts.add(new M(9));
        System.out.println(ts);
    }

}
[M对象(age:9), M对象(age:5), M对象(age:-3)]

EnumSet类
专门为枚举类设计的集合类,EnumSet所有值必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序决定集合元素的顺序。

  • EnumSet是以位向量的形式存储,占用内存很小运行效率高。
  • EnumSet无法加入null元素

总结

HashSet和TreeSet的选择

  • HashSet的性能相对好,优先
  • 当你需要一个保存排序的Set时,应该使用TreeSet。
  • LinkedHashSet由遍历优势,对于增删改查对于HashSet较慢。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值