哈希表 (Hash Table)
哈希表是一种数据结构,它通过哈希函数,能将任意'键'(Key)瞬间映射到一个'存储地址',从而实现极速的数据访问。在 Java 中,我们最常用的哈希表实现是 HashSet 和 HashMap。
- HashSet:一个'不重复的登记簿',只关心东西在不在。
- HashMap:一个'万能的键对值档案柜',能根据标签(Key)快速找到内容(Value)。
场景及优势
| 核心用法 (适用场景) |
|---|
哈希表通过哈希函数实现键到存储地址的映射,支持 O(1) 时间复杂度的数据访问。Java 中主要实现为 HashMap 和 HashSet。HashMap 存储键值对,Key 唯一,底层采用数组加链表加红黑树结构;HashSet 存储唯一元素,内部基于 HashMap 实现。两者均无序且非线程安全。适用场景包括存在性检查、键值对存取及数据去重。相比 ArrayList 等结构,哈希表在查找和插入性能上具有显著优势,但会占用更多内存且不保证顺序。
哈希表是一种数据结构,它通过哈希函数,能将任意'键'(Key)瞬间映射到一个'存储地址',从而实现极速的数据访问。在 Java 中,我们最常用的哈希表实现是 HashSet 和 HashMap。
| 核心用法 (适用场景) |
|---|
| 哈希表 (HashSet, HashMap) |
|---|
| 其他挑战者 (ArrayList, TreeSet 等) |
|---|
| 存在性检查 (在或不在?) | O(1) - 最快 | O(N) 或 O(log N) |
| 键值对存取 (根据 Key 找 Value) | O(1) - 最快 | O(N) 或 O(log N) |
| 数据去重 | O(N) - T0 级别 (遍历一次全放进去) | O(N log N) (先排序再去重) |
HashMap 是一个实现了 Map 接口的类,用于存储键值对。
核心特点:
HashMap 的底层是一个'数组 + 链表 + 红黑树'的结构。
首先,需要导入包:
import java.util.HashMap;
import java.util.Map;
a. 创建对象
// 创建一个键为 String,值为 Integer 的 HashMap
Map<String, Integer> userScores = new HashMap<>();
b. 添加或修改元素:put(key, value)
userScores.put("Alice", 95); // 添加
userScores.put("Bob", 88);
Integer oldScore = userScores.put("Alice", 100); // 修改,key 已存在,返回旧值 95
c. 获取元素:get(key)
Integer score = userScores.get("Bob"); // 返回 88
Integer nonExistentScore = userScores.get("David"); // 返回 null
d. 删除元素:remove(key)
userScores.remove("Bob"); // 删除键为 "Bob" 的键值对
e. 检查是否存在
boolean hasAlice = userScores.containsKey("Alice"); // true
boolean hasScore95 = userScores.containsValue(95); // false (因为 Alice 的分数已被修改为 100)
f. 获取大小和判空
int count = userScores.size();
boolean isEmpty = userScores.isEmpty();
g. 遍历 (三种方式)
// 1. 遍历键 (keySet)
for (String name : userScores.keySet()) {
System.out.println("Key: " + name + ", Value: " + userScores.get(name));
}
// 2. 遍历值 (values) - 如果只关心值
for (Integer s : userScores.values()) {
System.out.println("Value: " + s);
}
// 3. 遍历键值对 (entrySet) - 最高效的方式
for (Map.Entry<String, Integer> entry : userScores.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
HashSet 是一个实现了 Set 接口的类,用于存储唯一的元素。
核心特点:
HashSet 的内部实际上是一个 HashMap 实例。当你向 HashSet 中添加一个元素时,这个元素会作为 HashMap 的 key 存储,而 HashMap 的 value 则被一个固定的虚拟对象 PRESENT 占据。判断元素是否重复,其实就是判断 HashMap 中是否已存在这个 key。
首先,需要导入包:
import java.util.HashSet;
import java.util.Set;
a. 创建对象
// 创建一个存储 String 类型元素的 HashSet
Set<String> uniqueNames = new HashSet<>();
b. 添加元素:add(element)
add 方法会尝试添加一个元素。
boolean r1 = uniqueNames.add("Alice"); // true
boolean r2 = uniqueNames.add("Bob"); // true
boolean r3 = uniqueNames.add("Alice"); // false,因为 "Alice" 已存在
c. 删除元素:remove(element)
uniqueNames.remove("Bob"); // 删除 "Bob"
d. 检查是否存在:contains(element)
boolean hasAlice = uniqueNames.contains("Alice"); // true
boolean hasDavid = uniqueNames.contains("David"); // false
e. 获取大小和判空
int count = uniqueNames.size();
boolean isEmpty = uniqueNames.isEmpty();
f. 遍历
由于 HashSet 只有元素,没有键值对,遍历方式相对简单。
// 使用 for-each 循环遍历
for (String name : uniqueNames) {
System.out.println("Name: " + name);
}
// 也可以使用迭代器 (Iterator)
// java.util.Iterator<String> it = uniqueNames.iterator();
// while (it.hasNext()) {
// System.out.println(it.next());
// }
| 特性 | HashMap<K, V> | HashSet |
|---|---|---|
| 存储内容 | 键值对 (key-value) | 单个元素 (element) |
| 实现接口 | Map<K, V> | Set |
| 核心目的 | 建立 key 到 value 的映射关系 | 存储不重复的元素集合 |
| 唯一性 | Key 必须唯一 | 元素 (Element) 必须唯一 |
| 添加方法 | put(key, value) | add(element) |
| 获取方法 | get(key) 返回 value | 没有 get 方法,只能通过 contains 判断 |
| 判断重复 | 内部通过 key.hashCode() 和 key.equals() | 内部通过 element.hashCode() 和 element.equals() |
| 底层实现 | 数组 + 链表 + 红黑树 | 内部封装了一个 HashMap |
这是哈希表的看家本领。用 HashSet 可以实现闪电般的判断。
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
// 创建一个登记簿
HashSet<String> set = new HashSet<>();
set.add("张三");
set.add("李四");
// 瞬间检查'李四'是否已登记
if (set.contains("李四")) {
System.out.println("李四已经登记过了!");
}
}
}
HashMap 就像一个完美的档案柜,根据唯一的标签(Key)瞬间存取档案内容(Value)。
import java.util.HashMap;
public class Main {
public static void main(String[] args) {
// 创建一个'学号 -> 分数'的档案柜
HashMap<String, Integer> map = new HashMap<>();
map.put("S01", 95);
map.put("S02", 88);
// 根据学号"S01"瞬间拿到他的分数
int score = map.get("S01");
System.out.println("S01 的分数是:" + score);
// 输出:95
}
}
HashSet 天生不允许重复,是最高效的'去重神器'。
import java.util.ArrayList;
import java.util.HashSet;
public class Main {
public static void main(String[] args) {
// 一个有重复水果的列表
ArrayList<String> list = new ArrayList<>();
list.add("苹果");
list.add("香蕉");
list.add("苹果");
// 直接把列表'扔'进 HashSet,自动去重
HashSet<String> set = new HashSet<>(list);
System.out.println("去重之后:" + set);
// 输出:[苹果,香蕉]
}
}

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online