Java集合框架 Set接口实现类--HashSet存储结构 & HashSet拓展

Posted Z && Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java集合框架 Set接口实现类--HashSet存储结构 & HashSet拓展相关的知识,希望对你有一定的参考价值。

1. HashSet存储结构

注:hashSet存储过程:

  1. 根据hashCode计算保存的位置,如果位置为空,则直接保存,否则执行第二步。
  2. 执行equals方法,如果方法返回true,则认为是重复,拒绝存储,否则形成链表。

问题: 如何不让新增new出来的匿名对象 & 如何删除new出来的匿名对象?

首先这里有一个Person类:

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\\'' +
                ", age=" + age +
                '}';
    }
}

测试代码:

    public static void main(String[] args) {
        HashSet<Person> hashSet = new HashSet<>();
        Person p1 = new Person("小明", 21);
        Person p2 = new Person("小李", 22);
        Person p3 = new Person("小周", 21);
        //1.添加元素
        hashSet.add(p1);
        hashSet.add(p2);
        hashSet.add(p3);
        //重复,添加失败
        hashSet.add(p3);
        //直接new一个相同属性的对象,依然会被添加,不难理解。
        //假如相同属性便认为是同一个对象,怎么修改?
        hashSet.add(new Person("小明", 21)); // 添加成功
        System.out.println(hashSet.toString());
        //如何删除new出来的对象?
        System.out.println();
        hashSet.remove(new Person("小明", 21));
        System.out.println(hashSet.toString());
    }

假如相同属性便认为是同一个对象,怎么修改?
思路: 要解决该问题问题,可以重写hashCode和equals代码:

现在的Peson类: 重写了hashCode和equals方法

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int hashCode() {
    // 这样对象内容一样 对象的哈希值也相同
        return this.name.hashCode() + age;
    }

    @Override
    public boolean equals(Object obj) {
        //1.是否为同一对象
        if (this == obj) {
            return true;
        }
        //2.判断是否为空
        if (obj == null) {
            return false;
        }
        //3.判断是否是Student类型
        if (obj instanceof Person) {
            Person person = (Person) obj;
            //4.比较属性
            return this.name.equals(person.name) && this.age == person.age;
        }
        //不满足,返回false
        return false;
    }
}

再次运行刚刚的测试代码:

  • 可以发现已经解决了不让新增new出来的匿名对象 & 删除new出来的匿名对象的问题

2. HashSet拓展:

IDEA可以自动帮我们重写hashCode和equals方法

  1. 鼠标右键,选择Generate

  2. 选择equals()和hashCode()
    3. 点击next

  3. 选择判断对象相等的依据,然好点击next

  4. 与上一步同理

  5. 点击Finish

可以发现IDEA帮我们自动生成了2个方法:

运行刚刚的测试代码:

点进去hashCode源码:


发现hashCode方法底层实现为:

hashCode方法里为什么要使用31这个数字大概有两个原因:

  • 31是一个质数,这样的数字在计算时可以尽量减少散列冲突。
  • 可以提高执行效率,因为31*i=(i<<5)-i,31乘以一个数可以转换成位运算。


以上是关于Java集合框架 Set接口实现类--HashSet存储结构 & HashSet拓展的主要内容,如果未能解决你的问题,请参考以下文章

Java集合框架 Set接口实现类--TreeSet概述及使用

Java集合框架 Set接口实现类--HashSet的使用

Java知识33 集合框架 List接口 Map 和set多测师

Java_集合框架

Java集合类框架的基本接口有哪些?

JAVA集合框架包含的内容