Java中哈希在算法中的10大经典用法

 更新时间:2026年05月07日 09:17:05   作者:祈安_.  
Java中的哈希表,也称为散列表,是一种高效的数据存储结构,它利用了哈希函数将键(Key)映射到存储位置,从而实现快速访问,这篇文章主要介绍了Java中哈希的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

哈希的本质是用空间换时间,把查找从 O(n) 降到 O(1) 平均。

HashSet

存不存在 / 去重,用于判断某元素是否出现过、数组去重、集合交集

Set<Integer> set = new HashSet<>();

set.add(3);          // 添加元素
set.add(3);          // 重复元素不会加入
set.contains(3);     // 判断是否存在
set.remove(3);       // 删除元素

典型题:两数之和、数组去重、判断重复元素、两数组交集

HashMap

计数 / 映射,用于字符统计、频率统计、值到索引映射

Map<Integer, Integer> map = new HashMap<>();

for (int n : nums) {
    // 如果 n 不存在,默认返回 0,然后 +1
    map.put(n, map.getOrDefault(n, 0) + 1);
}

 两个Integer代表泛型,指key 和 value 都是整数,map.put(n, map.getOrDefault(n, 0) + 1);这行代码是哈希计数的经典写法,意思是给n做出现次数统计。map.getOrDefault(n, 0)去map里取n的值,如果n不存在,就返回默认值0map是指数组)。因为我们要统计出现次数,每遇到一次就加1。map.put(n, ...)代表把更新后的次数放回map里,如果n原来不存在,会自动创建。

典型题:字母异位词、出现次数最多的元素、前缀和 + 哈希、两数之和

TreeMap / TreeSet

有序哈希,用于需要自动排序、范围查询

Set<Integer> set = new TreeSet<>();
Map<Integer, Integer> map = new TreeMap<>();

基本用法:

TreeSet<Integer> set = new TreeSet<>();

        set.add(5);
        set.add(3);
        set.add(8);
        set.add(3); // 重复元素不会加入

        System.out.println(set); // [3, 5, 8] 自动升序
TreeMap<Integer, String> map = new TreeMap<>();

        map.put(3, "C");
        map.put(1, "A");
        map.put(2, "B");
        map.put(2, "BB"); // key=2 更新 value

        System.out.println(map); // {1=A, 2=BB, 3=C} 自动按 key 排序

LinkedHashMap / LinkedHashSet

保序哈希,用于保持插入顺序 + 哈希效率

Map<Integer, Integer> map = new LinkedHashMap<>();
Set<Integer> set = new LinkedHashSet<>();

基本用法:

 Set<Integer> set = new LinkedHashSet<>();

        set.add(3);
        set.add(1);
        set.add(5);
        set.add(1); // 重复元素不会加入

        System.out.println(set); // [3, 1, 5] 插入顺序保持

  Map<Integer, String> map = new LinkedHashMap<>();

        map.put(3, "C");
        map.put(1, "A");
        map.put(2, "B");
        map.put(2, "BB"); // key=2 更新 value

        System.out.println(map); // {3=C, 1=A, 2=BB} 插入顺序保持

哈希在算法中的 10 大经典用法

判断元素是否存在

Set<Integer> set = new HashSet<>();
if (set.contains(x)) {}

去重

Set<Integer> set = new HashSet<>();

for (int n : nums) {
    set.add(n);    // HashSet 自动去重
}

统计频率

Map<Integer, Integer> map = new HashMap<>();
for (int n : nums)
    map.put(n, map.getOrDefault(n, 0) + 1);

字符串计数(异位词)

int[] cnt = new int[26];
for (char c : s.toCharArray()) cnt[c - 'a']++;

两数之和(值 → 下标)

Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
    int need = target - nums[i];
    if (map.containsKey(need)) return new int[]{map.get(need), i};
    map.put(nums[i], i);
}

前缀和 + 哈希(子数组和为 k)

Map<Integer, Integer> map = new HashMap<>();
map.put(0, 1);
int sum = 0, res = 0;
for (int n : nums) {
    sum += n;
    res += map.getOrDefault(sum - k, 0);
    map.put(sum, map.getOrDefault(sum, 0) + 1);
}

两数组交集

Set<Integer> set = new HashSet<>();
for (int n : nums1) set.add(n);
Set<Integer> res = new HashSet<>();
for (int n : nums2) if (set.contains(n)) res.add(n);

判断重复元素

Set<Integer> set = new HashSet<>();
for (int n : nums)
    if (!set.add(n)) 
        return true;

分组(分类)

Map<String, List<String>> map = new HashMap<>();
for (String s : strs) {
    String key = sort(s);
    map.computeIfAbsent(key, k -> new ArrayList<>()).add(s);
}

最近最少使用缓存(LRU)

class LRUCache extends LinkedHashMap<Integer, Integer> {
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > capacity;
    }
}

数组哈希 vs Map 哈希

当 key 范围固定小(如 a-z):

int[] hash = new int[26];
hash[c - 'a']++;

当 key 范围大或不连续:

Map<Integer, Integer> map = new HashMap<>();

总结

到此这篇关于Java中哈希在算法中的10大经典用法的文章就介绍到这了,更多相关Java哈希用法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • IDEA创建Maven项目一直显示正在加载的问题及解决

    IDEA创建Maven项目一直显示正在加载的问题及解决

    这篇文章主要介绍了IDEA创建Maven项目一直显示正在加载的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • SpringCloud Gateway实现限流功能详解

    SpringCloud Gateway实现限流功能详解

    SpringCloud Gateway 是 Spring Cloud 的一个全新项目,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。这篇文章主要介绍了SpringCloud Gateway实现限流,需要的朋友可以参考下
    2022-11-11
  • Java通过Modbus简单实现数采的示例代码

    Java通过Modbus简单实现数采的示例代码

    本文介绍了Java通过Modbus简单实现数采,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-11-11
  • springboot中@Async默认线程池导致OOM问题

    springboot中@Async默认线程池导致OOM问题

    这篇文章主要介绍了springboot中@Async默认线程池导致OOM问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • 解读为何java中的boolean类型是32位的

    解读为何java中的boolean类型是32位的

    这篇文章主要介绍了为何java中的boolean类型是32位的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • 浅谈Java反射与代理

    浅谈Java反射与代理

    下面小编就为大家带来一篇浅谈Java反射与代理。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-07-07
  • Java中@RequiredArgsConstructor使用详解

    Java中@RequiredArgsConstructor使用详解

    这篇文章主要介绍了Java中@RequiredArgsConstructor使用的相关资料,@RequiredArgsConstructor是Lombok库提供的一个注解,用于自动生成一个包含所有final字段和非空字段的构造函数,需要的朋友可以参考下
    2025-05-05
  • Linux系统安装JDK三种主流的方式

    Linux系统安装JDK三种主流的方式

    这篇文章主要介绍了Linux系统安装JDK三种主流的方式,三种方式分别是YUM源仓库安装、RPM包手动安装和tar.gz压缩包手动安装,每种方式都有其特点和适用场景,需要的朋友可以参考下
    2026-02-02
  • 使用Spring Cache和Redis实现查询数据缓存

    使用Spring Cache和Redis实现查询数据缓存

    在现代应用程序中,查询缓存的使用已经变得越来越普遍,它不仅能够显著提高系统的性能,还能提升用户体验,在这篇文章中,我们将探讨缓存的基本概念、重要性以及如何使用Spring Cache和Redis实现查询数据缓存,需要的朋友可以参考下
    2024-07-07
  • JavaScript中的Map用法完全指南

    JavaScript中的Map用法完全指南

    这篇文章主要介绍了JavaScript中Map用法的相关资料,通过实例讲解了Map的创建、常用方法和迭代方式,还探讨了Map与对象的区别,并通过一个例子展示了如何使用Map来统计字符出现的次数,需要的朋友可以参考下
    2025-03-03

最新评论