Set集合

Collection集合的两大实现类Set接口和List接口中的Set接口

java.util.Set 接口和java.util.list接口是一样的,都是继承自Collection接口,他与Collection接口中的方法基本一样,没有对Collection接口进行功能上的扩展,只是比Collection接口更严格.与List接口不同的是Set接口中的元素是无序的,并且都会以某种规则保证存入的规则保证存入的元素不重复.

Set接口有很多子类,重要子类 "java.util.HashSet"和"java.util.LinkedHashSet"集合

Set集合取出元素的方式可以采用:迭代器,增强for循环.

java.util.hashSet 是Set接口的一个实现类,它存储的元素是不可重复的,并且元素都是无序的(存取顺序不一致),

java.util.HashSet 底层的实现其实是一个java.util.HashMap支持的.

HashSet是根据对象的哈希值来确定元素在集合当中的存储位置,因此它具有良好的存取和查找性能,保证元素的唯一性的方式依赖于"hashCode"和equals方法.

HashSet集合存储数据的结构(哈希表)

jdk1.8之前,哈希表=数组+链表

jdk1.8之后:哈希表=数组+链表还有另外一个 哈希表=数字+红黑树

jdk1.8之前,哈希表=数组+链表 即使用链表处理哈希冲突,同一哈希值的链表都存储在一个链表里,但是当位于一个链中的元素较多时,即hash值相等的元素较多时,通过key值依次查找的效率很低下.在jdk1.8中,哈希表存储结构采用数组+链表/红黑树实现的,当链表的长度超过阀值(8),将链表转换成红黑树结构,遮掩的还出事大大减少了查找时间

哈希值:通过一定算法为某个元素生成的十位数数字

哈希冲突:有一定的可能两个不同的值获得到一样的哈希值

hashSet就是为我们提供了解决哈希冲突的方法

通过重写的hashSet和equals方法来保证元素的唯一

总而言之,jdk1.8之后引入了红黑树结果大大优化了HashMap的性能,那么对于我们来讲保证HashSet元素唯一不重复其实是根据对象的hashCode方法和equals方法决定的,如果我们往集合当中存储的是自定义的对象,需要保证对象的唯一性,就必须重写Object的HashCode和equals方法,来自定义当前对象的比较方式.

HashSet存储自定义类型的元素

一般需要重写对象当中的HashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的元素的唯一性.一般的包装类中都已经重写了HashCode和equals方法,而我们如果在hashSet中存储的是自定义的对象,

该怎么比较判断,以下为自定义类中重写的equals

@Override
    public boolean equals(Object o){
        if(o==null){//判读放入的对象是否被初始化(非空校验)
          return false;
        }
        if(this==o){(判断放入的对象是否为自己,判断内存地址)
            return  true;
        }
        //向下转型 类型判断
        if(o instanceof Student){(经过上面判断已经确定o不是Null也不是自己,那么我们判断他是否为Student的实例)
            Student student=(Student)o;(如果是就向下转型)
            //同名同年龄的人为同一个人  true
            return student.getName().equals(name)&&student.getAge()==age;(相等判断)
        }
        return  false;
    }

以下为重写后的hashCode方法,

//重写的hashCode要求不高,只要求尽量保证各个元素的哈希值不一样,可随意自定义设定,不行还有equals方法Hash
@Override
    public int hashCode(){
        //使用Object类中的hash方法
        return Objects.hash(name,age);
    }

在java.util.HashSet类的下面还有一个子类java.util.LinkedHashSet,它是链表和哈希表组成的

LinkedHashSet

HashSet<String> hashSet = new HashSet<>();
        hashSet.add("www");
        hashSet.add("zhiyou100");
        hashSet.add("com");
        hashSet.add("abc");
        hashSet.add("abc1");
        System.out.println(hashSet);//[com, abc, www, zhiyou100]  无序的,不重复的
        //构建一个LinkedHashSet集合对象
        LinkedHashSet<String> strings = new LinkedHashSet<>();//同样实现了Set接口的子类集合,和HashSet极为相似,不同的是和HashSet集合相比,多了一条用来记录存入数据的链条,这使得LinkedHasSet集合的存入和输入顺序得以有序
        strings.add("www");
        strings.add("zhiyou100");
        strings.add("com");
        strings.add("abc");
        strings.add("abc");
        strings.add("java");
        strings.add("python");
        System.out.println(strings);//[www, zhiyou100, com, abc]有序的 不重复的

 

原文地址:https://www.cnblogs.com/rosiness/p/14083562.html