热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java集合框架深入解析:HashSet详解

本文详细介绍了HashSet类,它是Set接口的一个实现,底层使用哈希表(实际上是HashMap实例)。HashSet不保证元素的迭代顺序,并且是非线程安全的。

HashSet概述

HashSet是Java集合框架中的一个重要类,实现了Set接口。它内部使用哈希表(实际上是HashMap实例)来存储元素。HashSet不保证元素的迭代顺序,这意味着每次迭代的结果可能不同。此外,HashSet是非线程安全的,如果需要线程安全的Set,可以使用Collections.synchronizedSet方法进行包装:

Set s = Collections.synchronizedSet(new HashSet(...));

HashSet的特点

1. HashSet不维护任何顺序,元素将以随机顺序返回。

2. HashSet不允许有重复元素,如果尝试添加重复元素,添加操作将被忽略。

3. HashSet允许有一个null值,但多次插入null值只会保留一个。

4. HashSet是非线程安全的。

5. HashSet返回的迭代器是快速失败的,即在创建迭代器后修改HashSet会导致迭代器抛出ConcurrentModificationException异常,除非通过迭代器的remove方法进行修改。

HashSet的常用操作

1. 基本示例

package com.example.collection;

import java.util.HashSet;

public class HashSetExample {
    public static void main(String[] args) {
        // 创建HashSet
        HashSet hset = new HashSet<>();
        
        // 添加元素
        hset.add("Apple");
        hset.add("Mango");
        hset.add("Grapes");
        hset.add("Orange");
        hset.add("Fig");
        
        // 尝试添加重复元素
        hset.add("Apple");
        hset.add("Mango");
        
        // 尝试添加null值
        hset.add(null);
        hset.add(null);
        
        // 显示HashSet元素
        System.out.println(hset);
    }
}

输出:
[null, Apple, Grapes, Fig, Mango, Orange]

2. 删除所有元素

package com.example.collection;

import java.util.HashSet;

public class EmptyHashSetExample {
    public static void main(String[] args) {
        // 创建HashSet
        HashSet hset = new HashSet<>();
        
        // 添加元素
        hset.add("Element1");
        hset.add("Element2");
        hset.add("Element3");
        hset.add("Element4");
        hset.add("Element5");
        
        // 显示HashSet元素
        System.out.println("Before: HashSet contains: " + hset);
        
        // 清空HashSet
        hset.clear();
        
        // 再次显示HashSet元素
        System.out.println("After: HashSet contains: " + hset);
    }
}

输出:
Before: HashSet contains: [Element5, Element4, Element3, Element2, Element1]
After: HashSet contains: []

3. 迭代元素

3.1 使用Iterator

3.2 使用for-each循环

package com.example.collection;

import java.util.HashSet;
import java.util.Iterator;

public class IterateHashSet {
    public static void main(String[] args) {
        // 创建HashSet
        HashSet hset = new HashSet<>();
        
        // 添加元素
        hset.add("Chaitanya");
        hset.add("Rahul");
        hset.add("Tim");
        hset.add("Rick");
        hset.add("Harry");
        
        // 使用Iterator迭代
        System.out.println("----使用Iterator:");
        Iterator it = hset.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        
        // 使用for-each循环迭代
        System.out.println("----使用for-each循环:");
        for (String temp : hset) {
            System.out.println(temp);
        }
    }
}

输出:
----使用Iterator:
Chaitanya
Rahul
Harry
Tim
Rick
----使用for-each循环:
Chaitanya
Rahul
Harry
Tim
Rick

4. 转换为数组

package com.example.collection;

import java.util.HashSet;

public class ConvertHashSetToArray {
    public static void main(String[] args) {
        // 创建HashSet
        HashSet hset = new HashSet<>();
        
        // 添加元素
        hset.add("Element1");
        hset.add("Element2");
        hset.add("Element3");
        hset.add("Element4");
        
        // 显示HashSet元素
        System.out.println("HashSet contains: " + hset);
        
        // 转换为数组
        String[] array = new String[hset.size()];
        hset.toArray(array);
        
        // 显示数组元素
        System.out.println("Array elements:");
        for (String temp : array) {
            System.out.println(temp);
        }
    }
}

输出:
HashSet contains: [Element4, Element3, Element2, Element1]
Array elements:
Element4
Element3
Element2
Element1

5. 转换为TreeSet

package com.example.collection;

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

public class ConvertHashSetToTreeSet {
    public static void main(String[] args) {
        // 创建HashSet
        HashSet hset = new HashSet<>();
        
        // 添加元素
        hset.add("Element1");
        hset.add("Element2");
        hset.add("Element3");
        hset.add("Element4");
        
        // 显示HashSet元素
        System.out.println("HashSet contains: " + hset);
        
        // 转换为TreeSet
        Set tset = new TreeSet<>(hset);
        
        // 显示TreeSet元素
        System.out.println("TreeSet contains:");
        for (String temp : tset) {
            System.out.println(temp);
        }
    }
}

输出:
HashSet contains: [Element4, Element3, Element2, Element1]
TreeSet contains:
Element1
Element2
Element3
Element4

6. 转换为List/ArrayList

package com.example.collection;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class ConvertHashSetToList {
    public static void main(String[] args) {
        // 创建HashSet
        HashSet hset = new HashSet<>();
        
        // 添加元素
        hset.add("Steve");
        hset.add("Matt");
        hset.add("Govinda");
        hset.add("John");
        hset.add("Tommy");
        
        // 显示HashSet元素
        System.out.println("HashSet contains: " + hset);
        
        // 转换为ArrayList
        List list = new ArrayList<>(hset);
        
        // 显示ArrayList元素
        System.out.println("ArrayList contains: " + list);
    }
}

输出:
HashSet contains: [Matt, Steve, Govinda, John, Tommy]
ArrayList contains: [Matt, Steve, Govinda, John, Tommy]

HashSet与HashMap的比较

相同点

1. 两者都是非线程安全的。

2. 都不保证元素的顺序。

3. 从源码角度来看,HashSet内部使用HashMap来实现其操作。

4. 在添加、删除元素等操作时,两者的性能表现一致。

不同点

HashSetHashMap
实现的是Set接口实现的是Map接口
存储的是单个对象(元素或值),例如:[null, Apple, Grapes, Fig, Mango, Orange]存储的是键值对(Key-Value)
不允许有重复值不允许有重复键,但可以有多个重复值
只允许有一个null元素允许有一个null键,多个null值

推荐阅读
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文基于刘洪波老师的《英文词根词缀精讲》,深入探讨了多个重要词根词缀的起源及其相关词汇,帮助读者更好地理解和记忆英语单词。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Python自动化处理:从Word文档提取内容并生成带水印的PDF
    本文介绍如何利用Python实现从特定网站下载Word文档,去除水印并添加自定义水印,最终将文档转换为PDF格式。该方法适用于批量处理和自动化需求。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • Scala 实现 UTF-8 编码属性文件读取与克隆
    本文介绍如何使用 Scala 以 UTF-8 编码方式读取属性文件,并实现属性文件的克隆功能。通过这种方式,可以确保配置文件在多线程环境下的一致性和高效性。 ... [详细]
  • 本文提供了使用Java实现Bellman-Ford算法解决POJ 3259问题的代码示例,详细解释了如何通过该算法检测负权环来判断时间旅行的可能性。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 掌握远程执行Linux脚本和命令的技巧
    本文将详细介绍如何利用Python的Paramiko库实现远程执行Linux脚本和命令,帮助读者快速掌握这一实用技能。通过具体的示例和详尽的解释,让初学者也能轻松上手。 ... [详细]
  • 本文介绍如何使用阿里云的fastjson库解析包含时间戳、IP地址和参数等信息的JSON格式文本,并进行数据处理和保存。 ... [详细]
  • andr ... [详细]
author-avatar
虎爷在江湖
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有