You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

支持多键查询且不允许重复键的Java数据结构及第三方库选型咨询

解决方案

你的核心需求是两个独立唯一键索引、支持任意键查询、重复键插入拦截,现有通用数据结构没有完全匹配的开箱即用实现,推荐两种实现方式:

方案1:轻量自定义封装(推荐,无额外依赖、完全匹配需求)

基于两个HashMap分别维护PIN到车辆、驾驶证号到车辆的映射,插入时做双维度唯一校验,实现代码如下:

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

public class DualUniqueKeyStore<V> {
    private final Map<String, V> pinIndex = new HashMap<>();
    private final Map<String, V> licenseIndex = new HashMap<>();

    public synchronized void add(String pin, String driverLicense, V value) {
        // 校验两个键的唯一性
        if (pinIndex.containsKey(pin)) {
            throw new IllegalArgumentException("PIN " + pin + " 已被分配");
        }
        if (licenseIndex.containsKey(driverLicense)) {
            throw new IllegalArgumentException("驾驶证号 " + driverLicense + " 已被分配");
        }
        pinIndex.put(pin, value);
        licenseIndex.put(driverLicense, value);
    }

    public Optional<V> getByPin(String pin) {
        return Optional.ofNullable(pinIndex.get(pin));
    }

    public Optional<V> getByDriverLicense(String driverLicense) {
        return Optional.ofNullable(licenseIndex.get(driverLicense));
    }

    // 按需添加删除、清空等方法即可
}

用法示例

刚好匹配你预期的调用逻辑:

// 车辆枚举定义略
DualUniqueKeyStore<Car> store = new DualUniqueKeyStore<>();
store.add("pin-1", "driverLicense-1", Car.TOYOTA);
store.add("pin-2", "driverLicense-2", Car.FORD);
store.add("pin-1", "driverLicense-3", Car.FORD); // 抛出异常:PIN pin-1 已被分配

如果不需要线程安全,可以去掉add方法的synchronized关键字提升性能。

方案2:基于现有第三方库改造

如果你不想自己维护基础逻辑,也可以基于Guava的HashBasedTable做二次校验封装,插入前先判断行(PIN)和列(驾驶证号)是否已存在,存在就抛出异常:

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;

public class UniqueKeyTable<V> {
    private final Table<String, String, V> table = HashBasedTable.create();

    public synchronized void add(String pin, String driverLicense, V value) {
        if (table.containsRow(pin)) {
            throw new IllegalArgumentException("PIN " + pin + " 已被分配");
        }
        if (table.containsColumn(driverLicense)) {
            throw new IllegalArgumentException("驾驶证号 " + driverLicense + " 已被分配");
        }
        table.put(pin, driverLicense, value);
    }

    // 对应封装查询方法即可
}

这种方式可以复用Table已有的批量查询、遍历等能力,适合需要更多复杂操作的场景。

为什么HashBasedTable原生不符合需求

HashBasedTable是行+列的组合索引,仅会在同一行+同一列重复插入时覆盖旧值,只要行或列任意一个不同就允许插入,和你要求的单维度键全局唯一的逻辑不符,所以必须加前置校验。

内容的提问来源于stack exchange,提问作者Jon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 04:24:03