Set集合接口

Set接口与List接口最大的不同在于Set接口中的内容是不允许重复的,同时,Set接口并没有对Collection接口进场扩充,而List接口对Collection进行了扩充,因此,Set接口中也没有get()方法

Set接口包括:HashSet(无序存储)TreeSet(有序存储)

(1)HashSet 

特点:

 不能保证元素的排列顺序,顺序有可能发生变化
 不是同步的
 集合元素可以是null,但只能放入一个null

添加元素

public class TestHashSet {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();  //<>泛型,可以使任何数据类型
        Set<Integer> set1 = new HashSet<>(); //但是要包装类,这里不能是int型
        set.add("A");
        set.add("B");
        set.add("C"); //重复元素,被后一个覆盖,不在结果中
        set.add("C"); 
        set1.add(1);
        set1.add(2);
        set1.add(2); //重复元素
        set1.add(3);
        set1.add(4);
        System.out.println(set);
        System.out.println(set1);
    }
}

结果:

[A, B, C]
[1, 2, 3, 4]

Process finished with exit code 0

 看到这里你可能要迷惑了,HashSet不是无序存储嘛,怎么输出结果是有序的???emmm......听我慢慢说

当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据 hashCode值来决定该对象在HashSet中存储位置,这里其实只是Hash Code的算法上的巧合;在小范围内给人以有序的假象;

[A, B, C]
[8080, 1024, 1, 2, 3, 6, 10]

Process finished with exit code 0

当我插入几个大的数字的时候,输出结果就变成无序的了

总结:

(1)当输入的值大小和底层数组大小差不多的时候,HashSet的输入顺序是无序的,但输出是有序的,因为这些数的哈希值,在底层是顺序拍的,故输出也是有序的

(2)而当输入的值大小和底层数组相差很大时,大的数的哈希值有可能是小于比他小的数的,这时候输出的结果就是无序的。

(2)TreeSet

TreeSet是SortedSet接口的唯一实现类,TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。

自然排序使用要排序元素的CompareTo(Object obj)方法来比较元素之间大小关系,然后将元素按照升序排列。

添加元素

public class TestTreeSet {
    public static void main(String[] args) {
        Set<String> set = new TreeSet<>();
        Set<Integer> set1 = new TreeSet<>();
        set.add("C");
        set.add("C");  //重复元素
        set.add("A");
        set.add("B");
        set1.add(8080);
        set1.add(6);
        set1.add(1024);
        set1.add(3);
        set1.add(10);
        set1.add(1);
        set1.add(2);
        set1.add(2);  //重复元素
        System.out.println(set);
        System.out.println(set1);
    }
}

结果:

[A, B, C]
[1, 2, 3, 6, 10, 1024, 8080]

Process finished with exit code 0

由TreeSet的输出结果发现上面被HashSet输出的无序结果变为有序了,TreeSet会进行升序排列输出 

(3)重复元素判断 

在使用TreeSet子类进行数据保存的时候,重复元素的判断依靠的ComParable接口完成的。相等返回0,只要返回的是0,就代表元素重复

但是HashSet跟Comparable没有任何关系,所以它判断重复元素的方式依靠的是Object类中的两个方法:

    1. hash码: public native int hashCode();
    2. 对象比较:public boolean equals(Object obj);

也就是说如果要想标识出对象的唯一性,一定需要equals()与hashCode()方法共同调用。HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode()方法返回值相等

注意: 如果要把一个对象放入HashSet中,重写该对象对应类的equals方法,也应该重写其hashCode()方法。其规则是如果两个对 象通过equals方法比较返回true时,其hashCode也应该相同。另外,对象中用作equals比较标准的属性,都应该用来计算 hashCode的值。 

(4)HashSet和TreeSet的区别与联系

联系:

  • 都是Set的子接口
  •  单例集合
  • 都要求数据不可重复

区别:

  • HashSet是哈希表实现的,数据时候无序的,允许放入null值,但只能放入一个null
  • TreeSet是二叉树实现的,数据是自动排好序的,且是升序,不允许放入null值
  • Hashset是通过复写hashCode()方法和equals()方法来保证存储数据方式的唯一
  • Treeset是通过Compareable接口的compareto方法来保证存储数据方式的唯一
  • HashSet要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的,而具有相同内容的 String对象,hashcode是一样,所以放入的内容不能重复。但是同一个类的对象可以放入不同的实例 。

 

猜你喜欢

转载自blog.csdn.net/weixin_43224539/article/details/91374358
今日推荐