
java 的 set 本身不支持键值对结构,但可通过自定义 pair 类或利用 map.entry 实现真正意义上的“键+值”唯一组合存储,避免 map 中因键重复导致的值覆盖问题。
java 的 set 本身不支持键值对结构,但可通过自定义 pair 类或利用 map.entry 实现真正意义上的“键+值”唯一组合存储,避免 map 中因键重复导致的值覆盖问题。
在 Java 中,若需保存多个具有相同键但不同值的键值对(例如 (12, "Hello") 和 (12, "Hi")),标准 Map
✅ 推荐方案一:使用自定义 Pair 类(推荐,类型安全、可读性强)
通过封装键与值为不可变对象,并正确重写 equals() 和 hashCode(),即可让 HashSet
public final class Pair<l r> {
private final L key;
private final R value;
private Pair(L key, R value) {
this.key = key;
this.value = value;
}
public static <l r> Pair<l r> of(L key, R value) {
return new Pair(key, value);
}
public L getKey() { return key; }
public R getValue() { return value; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Pair, ?> pair = (Pair, ?>) o;
return Objects.equals(key, pair.key) && Objects.equals(value, pair.value);
}
@Override
public int hashCode() {
return Objects.hash(key, value);
}
@Override
public String toString() {
return "(" + key + ", " + value + ")";
}
}</l></l></l>
使用示例:
Set<pair string>> pairSet = new HashSet(); pairSet.add(Pair.of(12, "Hello")); pairSet.add(Pair.of(12, "Hi")); // ✅ 允许存在:与上一行不相等 pairSet.add(Pair.of(13, "Hello")); System.out.println(pairSet); // 输出示例:[(12, Hello), (12, Hi), (13, Hello)]</pair>
⚠️ 注意事项:
- Pair 必须是不可变(immutable) 的(所有字段 final),否则修改后可能破坏 HashSet 内部哈希表结构;
- equals() 与 hashCode() 必须保持一致,且仅依赖 key 和 value 字段;
- 若项目已引入 Guava 或 Apache Commons Lang,可直接使用 ImmutablePair 或 Pair,无需重复造轮子。
✅ 推荐方案二:复用 Map.Entry(零依赖、简洁)
Java 9+ 提供了静态工厂方法 Map.entry(K,V),返回一个不可变 Map.Entry 实例。它天然实现了符合集合要求的 equals()/hashCode()(基于 key 和 value),可直接用于 HashSet:
Set<map.entry string>> entrySet = new HashSet(); entrySet.add(Map.entry(12, "Hello")); entrySet.add(Map.entry(12, "Hi")); // ✅ 成功添加 entrySet.add(Map.entry(13, "Hello")); System.out.println(entrySet); // 输出示例:[12=Hello, 12=Hi, 13=Hello]</map.entry>
✅ 优势:无需额外类,JDK 原生支持,语义清晰;
❗ 局限:Map.Entry 的 toString() 格式为 "key=value"(非括号格式),且部分旧版 IDE 可能提示 Map.entry 不可用(需确保 JDK ≥ 9)。
❌ 不推荐的做法
- 使用 List
> 并手动遍历去重 → 时间复杂度 O(n),性能差; - 将键值拼接为字符串(如 "12#Hello")存入 HashSet
→ 易受分隔符冲突、类型丢失、可读性差等问题影响; - 误用 TreeSet 未提供比较器 → 抛出 ClassCastException。
总结
当业务逻辑需要保存键可重复、但“键+值”组合必须唯一的数据时,应放弃 Map,转而采用 Set
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











