栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Java集合框架】13——HashSet 类

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java集合框架】13——HashSet 类

一、HashSet 类的介绍

HashSet类实现了Set接口,其背后是一个哈希表,实际上是一个HashMap实例。不保证集合的迭代顺序,这意味着类不保证元素随时间的变化顺序不变。这个类允许使用空元素。这个类还为添加、删除、包含和大小等基本操作提供了恒定的时间性能,前提是哈希函数将元素适当地分散到存储桶中,我们将在本文中进一步介绍这些操作。

1.1 HashSet 的特性

HashSet的几个重要特性有:

  • 实现set接口。
  • HashSet的底层数据结构是Hashtable。
  • 因为它实现了Set接口,所以不允许重复的值。
  • 在HashSet中插入的对象不保证以相同的顺序插入。对象是根据其散列代码插入的。
  • HashSet中允许有NULL元素。
  • HashSet还实现了Serializable和Cloneable接口。
1.2 HashSet 的层次结构

HashSet的层次结构如下:

HashSet扩展了抽象集类,并实现了Set, Cloneable和Serializable接口,其中E是该集合维护的元素类型。HashSet的直接子类是LinkedHashSet。

现在为了维护恒定的时间性能,遍历HashSet需要的时间与HashSet实例的大小(元素的数量)加上后面的HashMap实例的“容量”(桶的数量)的总和成正比。因此,如果迭代性能很重要,那么初始容量不要设置得太高(或者负载因子太低)是非常重要的。

  • 初始容量:初始容量是指创建哈希表(HashSet内部使用哈希表数据结构)时的桶数。如果当前大小已满,则桶的数量将自动增加。
  • 负载因子:负载因子是在HashSet容量自动增加之前允许其达到的满度的度量。当哈希表中的条目数量超过负载因子和当前容量的乘积时,哈希表将被重新哈希(即重新构建内部数据结构),这样哈希表的存储桶数量大约是原来的两倍。

示例:如果内部容量为16,负载因子为0.75,那么当表中有12个元素时,桶的数量将自动增加。

对性能的影响:负载因子和初始容量是影响HashSet操作性能的两个主要因素。就时间和空间复杂度而言,0.75的负载因子提供了非常有效的性能。如果我们将负载因子值增加更多,那么内存开销将会减少(因为它会减少内部重建操作),但是,它会影响哈希表中的添加和搜索操作。为了减少重哈希操作,我们应该明智地选择初始容量。如果初始容量大于最大条目数除以负载因子,则不会发生重hash操作。

注意:HashSet中的实现不是同步的,也就是说,如果多个线程同时访问一个哈希集,并且至少有一个线程修改了这个集,那么它必须在外部同步。这通常通过对自然封装该集合的某些对象进行同步来完成。如果不存在这样的对象,则应该使用Collections“包装”集合。synchronizedSet方法。这最好在创建时完成,以防止意外的不同步访问集,如下所示:

Set s = Collections.synchronizedSet(new HashSet(...));
1.3 HashSet 的类的声明

HashSet 类的声明

public class HashSet extends AbstractSet implements Set, Cloneable, Serializable

其中E是存储在HashSet中的元素类型。
HashSet的内部工作方式:Set接口的所有类都由Map在内部备份。HashSet使用HashMap在内部存储它的对象。您一定想知道,要在HashMap中输入一个值,我们需要一个键值对,但在HashSet中,我们只传递了一个值。
存储在HashMap中:实际上,我们在HashSet中插入的值充当映射对象的键,java使用常量变量来表示它的值。因此,在键值对中,所有值都是相同的。

HashSet不仅存储唯一的对象,而且还存储唯一的对象集合,如ArrayList, LinkedList, Vector,…等等。

实例:

    public static void main(String[] args) {
        // 新建hashSet对象
        HashSet set = new HashSet<>();

        // 创建 ArrayList 列表1
        ArrayList list1 = new ArrayList<>();

        // 创建 ArrayList 列表2
        ArrayList list2 = new ArrayList<>();

        // list1 和list2 添加元素
        list1.add(1);
        list1.add(2);
        list2.add(1);
        list2.add(2);
        // 把 两个列表 添加到  HashSet 里面
        set.add(list1);
        set.add(list2);

        // 输出HashSet 的大小
        System.out.println(set);
        // hashSet 去掉重复的元素
        System.out.println(set.size());
    }

输出

[[1, 2]]
1

在存储Object之前,HashSet会使用hashCode()和equals()方法检查是否存在现有的条目。在上面的例子中,如果两个列表具有相同顺序的相同元素,则认为它们是相等的。当您在两个列表上调用hashCode()方法时,它们都将给出相同的散列,因为它们是相等的。

HashSet不存储重复的项目,如果你给了两个相等的对象,那么它只存储第一个,这里是list1。

1.4 HashSet 类的构造函数

HashSet类的构造函数

为了创建HashSet,我们需要创建HashSet类的一个对象。HashSet类由各种构造函数组成,这些构造函数允许创建HashSet。下面是这个类中可用的构造函数。

  • HashSet():此构造函数用于构建一个空HashSet对象,其中默认初始容量为16,默认负载因子为0.75。如果我们希望创建一个名为hs的空HashSet,那么,可以这样创建:
HashSet hs = new HashSet();
  • HashSet(int initialCapacity):T此构造函数用于构建一个空HashSet对象,其中initialCapacity在对象创建时指定。这里,默认的loadFactor保持0.75。
 HashSet hs = new HashSet(int initialCapacity);
  • HashSet(int initialCapacity, float loadFactor):这个构造函数用于构建一个空的HashSet对象,在创建对象时在其中指定initialCapacity和loadFactor。
HashSet hs = new HashSet(int initialCapacity, float loadFactor);
  • HashSet(Collection):该构造函数用于构建包含给定集合中所有元素的HashSet对象。简而言之,当需要从任何Collection对象到HashSet对象进行任何转换时,就使用这个构造函数。如果我们想创建一个名为hs的HashSet,可以这样创建:
HashSet hs = new HashSet(Collection C);
二、HashSet 类的操作 2.1 添加操作

为了向HashSet中添加元素,可以使用add()方法。但是,HashSet中不保留插入顺序。我们需要注意的是,不允许重复元素,并且忽略所有重复元素。

实例:

    public static void main(String[] args) {
        // new HashSet
        HashSet hs = new HashSet();

        // 添加元素
        hs.add("广州");
        hs.add("深圳");
        hs.add("珠海");
        hs.add("珠海"); // HashSet 具有去重功能

        // 打印元素
        System.out.println("HashSet 元素 : " + hs);
    }

输出:

HashSet 元素 : [广州, 珠海, 深圳]

2.2 删除操作

可以使用remove()方法从HashSet中删除这些值。

实例:

    public static void main(String[] args) {
        // new HashSet
        HashSet hs = new HashSet();

        // 添加元素
        hs.add("广州");
        hs.add("深圳");
        hs.add("珠海");

        // 打印元素
        System.out.println("HashSet 添加后元素 : " + hs);

        // 删除 珠海
        hs.remove("珠海");

        // 输出 删除珠海后的元素
        System.out.println("删除珠海后的元素 " + hs);

        // 删除不存在的元素,即返回false
        System.out.println("删除不存在的元素: "
                + hs.remove("东莞"));
    }

输出:

HashSet 添加后元素 : [广州, 珠海, 深圳]
删除珠海后的元素 [广州, 深圳]
删除不存在的元素: false
2.3 迭代操作

使用iterator()方法遍历HashSet中的元素。另外,最著名的方法是使用增强的for循环。

实例:

    public static void main(String[] args) {
        // new HashSet
        HashSet hs = new HashSet();

        // 添加元素
        hs.add("广州");
        hs.add("深圳");
        hs.add("珠海");

        // 打印元素
        System.out.println("HashSet 添加后元素 : " + hs);

        // 使用Hash的迭代器
        Iterator itr = hs.iterator();

        // 直到Set中只剩下一个元素为止
        while (itr.hasNext())

            // 遍历元素并打印它们
            System.out.print(itr.next() + ", ");
        System.out.println();

        // 使用增强的for循环进行遍历:for-each
        for (String s : hs)

            // 遍历元素并打印它们
            System.out.print(s + ", ");
        System.out.println();
    }

输出:

HashSet 添加后元素 : [广州, 珠海, 深圳]
广州, 珠海, 深圳, 
广州, 珠海, 深圳, 
2.4 操作时间复杂度

HashSet操作的时间复杂度:HashSet的底层数据结构是哈希表。因此,摊销(平均或通常情况)HashSet的添加、删除和查找(包含方法)操作的时间复杂度为O(1)。

三、HashSet 类的API

Hash 的方法

METHODDESCRIPTION
add(E e)用于添加指定的元素,如果该元素不存在,则返回false。
clear()用于从集合中删除所有元素。
contains(Object o)用于当元素在set中出现时返回true。
remove(Object o)用于删除集合中存在的元素。
iterator()用于返回一个遍历集合中元素的迭代器。
isEmpty()用于检查集合是否为空。如果为空则返回true,如果set的条件非空则返回false。
size()用于返回集合的大小。
clone()用于创建该集合的浅副本。

从类java.util.AbstractSet继承的方法

METHODDESCRIPTION
equals()用于验证对象与HashSet是否相等并比较它们。只有当两个HashSet都包含相同的元素时,该列表才会返回true,无论顺序如何。
hashcode()返回此集合的散列代码值。
removeAll(collection)此方法用于删除集合中存在于集合中的所有元素。如果该集合因调用而发生更改,则此方法返回true。

从类java.util.AbstractCollection继承的方法

METHODDESCRIPTION
addAll(collection) 此方法用于将上述集合中的所有元素追加到现有集合。元素是随机添加的,不遵循任何特定的顺序。
containsAll(collection) 此方法用于检查集合是否包含给定集合中的所有元素。如果集合包含所有元素,则该方法返回true;如果缺少任何元素,则返回false。
retainAll(collection)此方法用于保留集合中给定集合中提到的所有元素。如果该集合因调用而发生更改,则此方法返回true。
toArray()此方法用于形成与Set的相同元素的数组。
toString()Java HashSet的toString()方法用于返回HashSet集合元素的字符串表示形式。

接口java.util.Collection中声明的方法

METHODDESCRIPTION
parallelStream()返回一个可能并行的流,并将此集合作为其源。
removeIf(Predicate filter)删除此集合中满足给定谓词的所有元素。
stream()返回一个序列流,并将此集合作为其源。
toArray(IntFunction generator)返回包含此集合中所有元素的数组,使用提供的生成器函数分配返回的数组。

接口java.lang.Iterable中声明的方法

METHODDESCRIPTION
forEach(Consumer action)对Iterable中的每个元素执行给定的操作,直到所有元素都被处理完或该操作引发异常。

接口java.util.Set中声明的方法

MethodDescription
add(element)此方法用于向集合中添加特定元素。该函数只在指定的元素不在集合中时才添加该元素,否则如果该元素已经在集合中存在,则返回False。
addAll(collection)此方法用于将上述集合中的所有元素追加到现有集合。元素是随机添加的,不遵循任何特定的顺序。
clear()此方法用于从集合中删除所有元素,但不删除集合。对集合的引用仍然存在。
contains(element)此方法用于检查Set中是否存在特定元素。
containsAll(collection)此方法用于检查集合是否包含给定集合中的所有元素。如果集合包含所有元素,则该方法返回true;如果缺少任何元素,则返回false。
hashCode()此方法用于获取Set的这个实例的hashCode值。它返回一个整数值,它是Set的这个实例的hashCode值。
isEmpty()此方法用于检查集合是否为空。
iterator()这个方法用于返回集合的iterator。集合中的元素以随机的顺序返回。
remove(element)这个方法用于从集合中删除给定的元素。如果指定的元素在Set中存在,此方法返回True,否则返回False。
removeAll(collection)此方法用于删除集合中存在于集合中的所有元素。如果该集合因调用而发生更改,则此方法返回true。
retainAll(collection)此方法用于保留集合中给定集合中提到的所有元素。如果该集合因调用而发生更改,则此方法返回true。
size()这种方法用于获取集合的大小。这将返回一个表示元素数量的整数值。
toArray()此方法用于形成与Set的相同元素的数组。
四、HashSet 类的源码分析

待续

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1036456.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号