随笔- 37  文章- 0  评论- 0  阅读- 1012 

Java

Set系列集合

特点

  • 无序: 存取顺序不一致(无序次数只有一次)
  • 不重复:可去除重复
  • 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素

实现类特点

  • HashSet :无序,不重复,无索引
  • LinkedHashSet : 有序,不重复,无索引
  • TreeSet : 排序,不重复,无索引

Set集合的功能基本上与Collection的API一致

HashSet底层原理

  • HashSet集合底层采取哈希表存储的数据
  • 哈希表是一种对于增删改查数据都较好的数据结构
哈希表组成
  • JDK 8 之前的, 底层使用数组+链表组成
  • JDK 8 开始后,底层采用数组+链表+红黑树组成
哈希值
  • 是JDK根据对象的地址,按照某种规则算出来的int类型的数值
Object类的API
  • public int hashCode(); 返回对象的哈希值
对象的哈希值特电
  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
  • 默认情况下,不同对象的哈希值是不同的
HashSet1.7版本的原理解析:数组+链表+(结合哈希算法)
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
  1. 创建应该默认长度为16的数组,数组名为table

  2. 根据元素的哈希值跟数组的长度求余计算出应存入的位置(哈希算法)

  3. 判断当前位置是否为null,表示有元素,则调用equals方法比较

  4. 如果一样,则不存,如果不一样,则存入数组

    • JDK 7新元素占老元素位置,指向老元素
    • JDK 8中新元素挂在老元素的下面

结论:哈希表是一种对于增删改查数据性能都较好的结构

JDK 8 版本开始HashSet原理解析
  • 底层结构:哈希表(数组,链表,红黑树的结合体)
  • 当挂在元素下面的数据过多时,查询性能下降,从JDK8 开始后,当链表长度超过8的时候,自动转换为红黑树

结论:JDK 8 开始后,哈希表对于红黑树的引入进一步提高了操作数据的性能.

JDK 8哈希表的详细流程
  1. 创建一个默认长度为16,默认加载因为0.75的数组,数组名table
  2. 根据元素的哈希值跟数组的长度计算出应存入的位置
  3. 判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素,则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数据
  4. 当数组存满到16*0.75 = 12 时,就自动扩容,每次扩容原先的两倍
HashSet去重复原理解析
  1. 创建一个默认长度为16的数组,数组名table
  2. 根据元素的哈希值跟数组的长度求余,计算出应存入的位置(哈希算法)
  3. 判断当前位置是否为null,如果null直接存入
  4. 如果位置不为null,表示有元素,则调用equals方法比较
  5. 如果一样,则不存,如果不一样,则存入数组

结论 : 如果希望Set集合认为2个内容一样的对象重复的,必须重写对象的hashCode()和equals()方法

package com.yu.HashCollection;

import java.util.HashSet;
import java.util.Set;

public class HashStudens {
    public static void main(String[] args) {
        Set<Student> sets = new HashSet<>();

        Student s1 = new Student("余" ,"19","男");
        Student s2 = new Student("余" ,"19","男");
        Student s3 = new Student("习" ,"20","男");
        Student s4 = new Student("xi" ,"21","男");

        sets.add(s1);
        sets.add(s2);
        sets.add(s3);
        sets.add(s4);

        System.out.println(sets);
    }


}
package com.yu.HashCollection;

import java.util.Objects;
import java.util.Set;

public class Student {
    private String name;
    private String id;
    private String sex;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name) && Objects.equals(id, student.id) && Objects.equals(sex, student.sex);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, id, sex);
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id='" + id + '\'' +
                ", sex='" + sex + '\'' +
                '}';
    }

    public Student() {
    }

    public Student(String name, String id, String sex) {
        this.name = name;
        this.id = id;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

运行结果

[Student{name='xi', id='21', sex='男'}, Student{name='余', id='19', sex='男'}, Student{name='习', id='20', sex='男'}]

 posted on   yulll  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示