HashSet的学习

HashSet的学习

一,HashSet的继承关系
HashSet 是 Set 的一个实现类,而 Set 又继承了Collection 方法,并且没有添加多余的方法。HashSet 继承了AbstractSet 类。
实现了 Cloneable 接口,说明它重写了clone()方法,可以被克隆。实现了 java.io.Serializable 接口,说明它可以被序列化。下面我们看一下源码是如何表示的:

extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable
{

二,HashSet的特点
通过源码的解读,我们发现以下四个特点:

1.数据重复性:不能重复 => 底层基于hashmap,hashmap的key是不能重复的,hashset存储的值就是hashmap的key
2.null值处理:只能存在一个null值
3.只能存储单个数据
4.插入数据是无序的

三,基本属性
HashSet的源码中给我们展示了他的三个特有的属性,其余都是继承自HashMap:
map 存储的是键值对,在这里我们只用到了它的 key ,Object 是用来给它的 value 赋值的。所以 HashSet 拥有 HashMap 的所有特性,是用数组加链表的数据结构,并且每个 key 值是唯一的。

	
	static final long serialVersionUID = -5024744406713321676L;

	//hashmap类型的map
    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

四,构造函数
HashSet拥有五个构造函数:
在这里插入图片描述
他们的作用都是对数据结构进行初始化定义,初始大小和容量的初始化等。

五,方法
在HashSet中有:contians,add,remove,iterator,clear,clone等方法,今天我们着重讲一下的他的add方法,首先我们看他在源码中是如何表示的:
在这里插入图片描述
我们看到在这个add方法中,传入连个参数,一个是所要插入的元素,一个是HashSet特有的属性PRESENT,然后调用父类HashMap的“put”方法 。这样这个add方法就与我们之前学习HashMap的方法是一致的。有兴趣的可以回看我们之前的HashMap的文章。

六,重点问题
我们之前提到了HashSet是一个单个数据,并且是不重复的,但是他又是继承与HashMap,是一个键值对形式,那么他到底是如何将数据转化为单个元素的呢?
那么就要回到源码当中来,我们发现这样了两个方法:

在这里插入图片描述
就是这两个方法,将我们add进来的键值对形式的元素转化为单个元素的形式。在writeObject中,调用了一些方法,然后foreach循环遍历他的键值对的key,然后打印出来。
所以在这里我们只用到了HashMap的 key ,Object 是用来给它的 value 赋值的。这就解释了为什么HashSet为什么是单个元素,并且是无重复的数据了。

七,方法的使用
下面我们将对HashSet的一些常用方法进行使用:

import java.util.HashSet;

/**
 * 描述:HashSet
 */
public class HashSetGY2 {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add(2);
        hashSet.add(2);
        hashSet.add(6);
        hashSet.add(9);
        hashSet.remove(45);
        System.out.println(hashSet);
        System.out.println(hashSet.remove(45));
        System.out.println(hashSet.size());
    }
}

打印结果:

C:\java\java7\jdk1.7.0_80\bin\java.exe -javaagent:D:\ideaIU-2018.1.5.win\lib\idea_rt.jar=41932:D:\ideaIU-2018.1.5.win\bin -
[2, 6, 9]
false
3

Process finished with exit code 0

如果我们随机打印出三个数据,可以重复,然后我们要求要将这三十个数据中出现重复的数据进行删除,如何呢进行呢?

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Random;

/**
 * 描述:删除30个数据中的重复数据
 */
public class Test1 {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList();
        Random random = new Random();
        for (int i = 0; i < 30; ++i) {
            arrayList.add(random.nextInt(30) + 1);
        }
        System.out.println(arrayList);
        HashSet<Integer> hashSet = new HashSet();
        for (int j = 0; j < 30;++j){
            hashSet.add(arrayList.get(j));
        }
        System.out.println(hashSet);
    }
}

打印结果:

C:\java\java7\jdk1.7.0_80\bin\java.exe -javaagent:D:\ideaIU-2018.1.5.win\lib\idea_rt.jar=41956:D:\ideaIU-2018.1.5.win\bin -
[11, 3, 24, 22, 21, 30, 16, 15, 24, 18, 30, 16, 25, 1, 14, 22, 24, 24, 25, 11, 16, 28, 10, 18, 8, 7, 24, 10, 13, 2]
[1, 2, 3, 7, 8, 10, 11, 13, 14, 15, 16, 18, 21, 22, 25, 24, 28, 30]

Process finished with exit code 0

在这里我们采用ArrayList来存储30个可以重复的数据,根据ArrayList的特性,然后将这30个数据add到HashSet中去,在打印,他就会自己将重复的数据删除了。当然也可以采用HashMap,然后遍历打印他的key值就行。

猜你喜欢

转载自blog.csdn.net/weixin_42262357/article/details/83901813