专业的JAVA编程教程与资源

网站首页 > java教程 正文

32. HashSet全解析,无序去重探秘

temp10 2025-07-28 00:00:54 java教程 3 ℃ 0 评论

32.1 HashSet 的核心特性:唯一性与哈希存储

HashSet是 “去重的图书馆书架”,每本书(元素)只能放一本,且通过 “哈希编号” 快速找到书的位置。它内部基于哈希表实现,元素通过哈希值确定存储位置,天然支持去重特性。

add(E e):添加元素到集合;

32. HashSet全解析,无序去重探秘

size():返回集合中元素的数量;

contains(Object o):检查元素是否存在;

add(null):允许添加一个 null 值,重复添加无效。

代码示例如下:

package com.set.demo;

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

/**
 * @author 今日头条:老陈说编程
 * HashSet的基本特性及去重功能演示
 * 本示例展示了HashSet的核心特性:不允许重复元素、允许null值(仅一个)、无序性
 */
public class HashSetBasicFeatures {
    public static void main(String[] args) {
        // 1. 创建HashSet实例
        // 使用接口Set声明变量,遵循面向接口编程原则
        Set<String> books = new HashSet<>();

        // 2. 添加元素:add(E e)
        // 向集合添加元素,如果元素已存在则返回false
        // HashSet通过元素的hashCode()和equals()方法判断重复
        books.add("Java核心技术");
        books.add("数据结构与算法");
        boolean added = books.add("Java核心技术"); // 重复元素,添加失败 
        System.out.println("添加重复元素结果:" + added); // 输出false 

        // 3. 查看集合大小:size()
        // 返回集合中元素的数量(去重后)
        System.out.println("集合元素数量:" + books.size()); // 输出2 

        // 4. 添加null值
        // HashSet允许添加一个null值,重复添加无效
        books.add(null);
        books.add(null); // 重复null,添加失败 
        System.out.println("含null的集合:" + books); // 输出[null, 数据结构与算法, Java核心技术] 

        // 5. 检查元素存在性:contains(Object o)
        // 通过hashCode()和equals()判断元素是否存在
        System.out.println("包含Java书:" + books.contains("Java核心技术")); // 输出true 
    }
} 

32.2 增删查:HashSet 的核心操作

操作HashSet就像 “管理哈希货架”—— 上架(add)时自动去重,下架(remove)时按 “哈希编号” 快速定位,查看(contains)时无需遍历整个货架!

add (E e):将元素添加到集合中,添加成功返回 true,元素已存在返回 false;

remove (Object o):从集合中移除指定元素,成功移除返回 true,否则返回false;

contains (Object o),检查元素是否存在于集合中,有返回true,否则返回false;

遍历集合:增强 for 循环、迭代器,不保证插入顺序,取决于内部哈希表的实现。

代码示例如下:

package com.set.demo;
import java.util.Set;
import java.util.HashSet;
/**
 * @author 今日头条:老陈说编程
 * HashSet的增删改查操作及去重逻辑演示
 * 本示例展示了HashSet的基本操作:添加、删除、查询、遍历,以及去重机制
 */
public class HashSetOperations {
    public static void main(String[] args) {
        // 1. 创建HashSet存储整数
        // HashSet内部使用HashMap实现,元素存储在HashMap的key中
        Set<Integer> numbers = new HashSet<>();

        // 2. 添加元素:add(E e)
        // 向集合添加元素,如果元素已存在则返回false
        // Integer的hashCode由值本身决定,相同值的Integer哈希码相同
        numbers.add(10);
        numbers.add(20);
        numbers.add(30);
        System.out.println("初始集合:" + numbers); // 输出顺序不固定,如[20, 10, 30] 

        // 3. 添加重复元素(去重)
        // 重复添加相同值的Integer会被去重
        numbers.add(10);
        System.out.println("去重后集合:" + numbers); // 仍为[20, 10, 30] 

        // 4. 删除元素:remove(Object o)
        // 删除指定元素,成功删除返回true,否则返回false
        boolean removed = numbers.remove(20);
        System.out.println("删除20:" + removed + ",剩余集合:" + numbers); // true, [10, 30] 

        // 5. 检查元素存在性:contains(Object o)
        // 通过hashCode和equals判断元素是否存在
        System.out.println("包含10:" + numbers.contains(10)); // true 
        System.out.println("包含5:" + numbers.contains(5)); // false 

        // 6. 遍历集合(无序)
        // 使用增强for循环遍历集合,顺序由内部哈希表决定
        System.out.println("遍历集合:");
        for (Integer num : numbers) {
            System.out.println(num);
        }
    }
} 

32.3 遍历方式:迭代器与增强 for 循环

遍历HashSet就像 “按哈希货架顺序取书”,由于元素位置由哈希值决定,遍历顺序可能与插入顺序不同。推荐用迭代器或增强 for 循环,不支持按索引访问(因无序)。

增强 for 循环:代码简洁,适用于简单遍历场景,仅读取集合元素,不进行修改

迭代器(Iterator):支持遍历时安全删除元素,可实现双向遍历

代码示例如下:

package com.set.demo;

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

/**
 * @author 今日头条:老陈说编程
 * HashSet的遍历方式及安全删除演示
 * 本示例展示了HashSet的三种遍历方式,并演示了迭代器的安全删除操作
 */
public class HashSetTraversal {
    public static void main(String[] args) {
        Set<String> fruits = new HashSet<>();
        fruits.add("苹果");
        fruits.add("香蕉");
        fruits.add("橘子");
        fruits.add("葡萄");

        // 1. 增强for循环(简洁,推荐)
        // 优点:代码简洁,适用于只读操作
        // 缺点:遍历过程中不能修改集合结构(增删元素)
        System.out.println("增强for循环遍历:");
        for (String fruit : fruits) {
            System.out.println(fruit);
        }

        // 2. 迭代器遍历(可安全删除)
        // 优点:支持在遍历过程中安全删除元素
        // 原理:迭代器内部维护了对集合修改次数的检查
        System.out.println("\n迭代器遍历并删除:");
        Iterator<String> it = fruits.iterator();
        while (it.hasNext()) {
            String fruit = it.next();
            if (fruit.equals("香蕉")) {
                it.remove(); // 安全删除当前元素,不会触发ConcurrentModificationException
            }
        }
        System.out.println("删除后集合:" + fruits); // 输出[苹果, 橘子, 葡萄] 

        // 3. 不推荐的遍历方式:转为数组后遍历(效率较低)
        // 缺点:需要额外空间存储数组,且失去了集合动态特性
        System.out.println("\n转为数组遍历:");
        Object[] fruitArray = fruits.toArray();
        for (Object fruit : fruitArray) {
            System.out.println(fruit);
        }
    }
} 

总结:HashSet 的适用场景

需要元素唯一性:如去重处理、统计不重复数据(用户 ID、商品编号等);

快速查找场景:比LinkedList的contains()方法效率高;

无序数据存储:若需要有序,可使用LinkedHashSet(维护插入顺序)或TreeSet(自动排序);

下期将讲解集合中的TreeSet,记得点赞关注,评论区留下你遇到的HashSet问题,我们一起解决!

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表