美文网首页程序员
深入了解HashSet

深入了解HashSet

作者: kangyiii | 来源:发表于2017-06-23 14:42 被阅读0次

我们知道Java中HashSet是Set的一个子类,其主要特点是存储的元素无序且不重复。
这里先举个例子,来演示HashSet的一些特性:

/**
     * @param args
     * Set集合,无索引,不可以重复,无序(存取不一致)
     */
public static void demo1() {
        HashSet<String> hs = new HashSet<>();                   //创建HashSet对象
        boolean b1 = hs.add("a");
        boolean b2 = hs.add("a");                               //当向set集合中存储重复元素的时候返回为false
        hs.add("b");
        hs.add("c");
        hs.add("d");
        System.out.println(hs);                                 //HashSet的继承体系中有重写toString方法
        System.out.println(b1);
        System.out.println(b2);
        
        for (String string : hs) {                              //只要能用迭代器迭代的,就可以使用增强for循环遍历
            System.out.println(string);
        }
    }

打印机结果:

[d,b,c,a]
true
false
d
b
c
a

我们发现添加的字符串元素为a,a,b,c,d,打印确实d,b,c,a,的确是无序且唯一。接下来我们来看看HashSet存储自定义对象如何保证元素的唯一性。

我先定义了一个Person类,类成员变量有age和name,之后使用Hashset去添加几个person对象,例子如下:

/**
     * 自定义类Person
     */
public class Person implements Comparable<Person> {
    private String name;
    private int age;
    public Person() {
        super();
        
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
/**
     * 添加几个person对象到hashSet中
     */
public static void demo1() {
        HashSet<Person> hs = new HashSet<>();
        hs.add(new Person("张三", 23));
        hs.add(new Person("张三", 23));
        hs.add(new Person("李四", 24));
        hs.add(new Person("李四", 24));
        hs.add(new Person("李四", 24));
        hs.add(new Person("李四", 24));
        
        System.out.println(hs.size());
        System.out.println(hs);
    }

打印结果:

6
[Person [name=李四,age=24],Person [name=李四,age=24],Person [name=李四,age=24],Person [name=李四,age=24],Person [name=张三,age=23],Person [name=张三,age=23]]

从打印结果我们可以看到HashSet将重复的name和age存进去了,原因很好解释,每当new一个新对象,会有一个新内存地址,而name和age只是对象内部的属性,内存地址没有重复,符合hashSet的唯一性这一特点。那我们的需求是只要同姓名同年龄的person对象,我们就认为它是同一对象。该怎么做呢?有的朋友可能会想到在Person类中重写equels方法,我们来尝试一下:

@Override
    public boolean equals(Object obj) {
        Person p = (Person)obj;
        System.out.println("我被调用了");
        return this.name.equals(p.name)&&this.age==p.age;
        }       

经过测试,发现重写的equels()方法并没有被调用,所以我们需要做的是能让equels()方法调用,才能实现只要同姓名同年龄的person对象,我们就认为它是同一对象的需求。

其实,HashSet中添加对象元素时判断其唯一性是通过一个叫做hashCode的方法决定,hashCode相同才会调用equels()。而在Person类中重写hashCode(),并将返回值设置为一个固定特殊的值,让每一个对象的hashCode都相同,才会触发重写的equels()方法,代码如下:

@Override
    public boolean equals(Object obj) {
        Person p = (Person)obj;
        System.out.println("我被调用了");
        return this.name.equals(p.name)&&this.age==p.age;
        }   
    @Override
    public boolean equals(Object obj) {
        return 10;                          
    }

打印结果:

我被调用了
我被调用了
我被调用了
我被调用了
我被调用了
[Person [name=李四,age=24],Person [name=张三,age=23]]

这时我们发现HashSet存储自定义对象保证元素的唯一性的问题就被解决了。
其实它的内部原理也非常简单

原理图

如果我们使用的开发工具是eclipse,直接alt+shift+s自动生成重写的hashCode()和equels()即可,使用自动生成的代码,还能有效减少调用equels()的次数,提高运行效率。


eclipse自动生成hashCode()和equels()

相关文章

  • 深入了解HashSet

    我们知道Java中HashSet是Set的一个子类,其主要特点是存储的元素无序且不重复。这里先举个例子,来演示Ha...

  • HashSet深入

    当将第一个元素改为3时,集合中的一三元素完全相同,这表明这两个元素已经重复,但是HashSet把它们两个添加到不同...

  • 深入理解HashSet

    题外话 今天下午去面试了一家公司,被问了一个问题,HashSet是因为什么保证元素可以不重复。感觉答的磕磕绊绊的,...

  • HashSet实现原理分析(Java源码剖析)

    本文将深入讨论HashSet实现原理的源码细节。在分析源码之前,首先我们需要对HashSet有一个基本的理解。 H...

  • Java 集合

    集合主要技术了解Collection和MapCollection接口ArrayList类HashSet类HashM...

  • 深入Java基础(四)--哈希表(2)HashTable与Has

    又突然想看源码了,继续深入Java基础系列。今天是研究JavaAPI的HashTable和HashSet(顺带讨论...

  • java8中hashset源码分析

    分析大纲 hashset实现原理 hashset代码分析 1. hashset实现原理 hashset存储无序,不...

  • HashSet的用法

    java集合——HashSet的用法 一、HashSet的构造 二、HashSet添加元素 三、遍历HashSet...

  • HashSet, LinkedHashSet源码

    目录 HashSet LinkedHashSet HashSet 对于HashSet而言,它是基于HashMap实...

  • 深入理解-HashSet源码解读

    HashSet HashSet的源码很简单,继承自AbstractSet,实现了Set, Cloneable...

网友评论

    本文标题:深入了解HashSet

    本文链接:https://www.haomeiwen.com/subject/txfccxtx.html