首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >具有多个键且不允许重复键的Java数据结构

具有多个键且不允许重复键的Java数据结构
EN

Stack Overflow用户
提问于 2021-11-06 00:40:39
回答 2查看 64关注 0票数 1

我想知道是否有任何Java数据结构或库可以让我在没有重复键的情况下拥有多个键?

在我的用例中,我有两种不同类型的密钥:个人识别码和驾照。我想使用这两个键中的任何一个来查找一个值(本例中是他们的汽车)。当我试图添加一个重复的键( pin-1 )时,应该会出现错误,因为pin-1已经被分配了。

代码语言:javascript
复制
structure.add("pin-1", "driverLicense-1", Car.TOYOTA);
structure.add("pin-2", "driverLicense-2", Car.FORD);
structure.add("pin-1", "driverLicense-3", CAR.FORD); // invalid because pin-1 is already assigned

我遇到的唯一这样做的库是谷歌的Guava及其实现TableHashBasedTable类。我对这个库的问题是它不能防止重复的键。

代码语言:javascript
复制
Table<String, String, Car> table = HashBasedTable.create();
table.put("pin-1", "driverLicense-1", Car.TOYOTA);
table.put("pin-2", "driverLicense-2", Car.FORD);
table.put("pin-1", "driverLicense-3", Car.FORD); // is valid
EN

回答 2

Stack Overflow用户

发布于 2021-11-06 00:55:24

我会使用两个Map,封装在一个类中,一起处理它们的更新,例如:

代码语言:javascript
复制
    class CarOwnership {
        private final Map<String,Car> byPin = new HashMap<>();
        private final Map<String,Car> byLicense = new HashMap<>();
        
        public void put(String pin, String licence, Car car) {
            if (byPin.containsKey(pin)) {
                throw new RuntimeException("duplicate pin " + pin);
            }
            if (byLicense.containsKey(licence)) {
                throw new RuntimeException("duplicate licence " + license);
            }
            byPin.put(pin, car);
            byLicense.put(licence, car);
        }
        
        public Car findByPin(String pin) {
            return byPin.get(pin);
        }
        ...
    }

在您正在使用的实际数据结构周围使用容器的好处是,它允许您将错误处理放在一个位置,并为您提供执行验证的地方。

这与HashBasedTable有所不同,后者是一种Map of Map,因此需要两个密钥组件才能达到值。

票数 4
EN

Stack Overflow用户

发布于 2021-11-06 07:06:51

据我所知,这可以通过在映射中为每个传递的键创建一个条目来实现。因此,只有一个映射,但是每次调用put()都可能添加多个条目(每个键对应一个条目)。不确定Java中是否有内置的API来实现这一点,但这里有一个简单的实现。

代码语言:javascript
复制
public class MultikeyMap<K, V>{
    /* Holds all the values. */
    private Map<K, V> map = new HashMap<>();
    
    /** Creates one entry in this.map for each key passed here. */
    public void put( V value, K... keys ) {
        if( keys == null || keys.length == 0 ) throw new NullPointerException();
        
        /* For every key, create an entry. */
        for( K key : keys ) map.putIfAbsent( key, value );
    }
    
    public V get( K key ) {
        if( key == null ) throw new NullPointerException();
        return map.get( key );
    }
    
    @Override
    public String toString(){
        return this.map.toString();
    }
    
    public static void main( String[] args ){
        MultikeyMap<String, Car> m = new MultikeyMap<>();
        
        m.put( Car.HONDA, "pin-1", "dl-1" );
        System.out.println( m );
        
        m.put( Car.TATA, "pin-2", "dl-2" );
        System.out.println( m );
        
        m.put( Car.TOYOTA, "pin-1", "dl-3" );
        System.out.println( m );
    }
    
    private static enum Car{
        TOYOTA, HONDA, MARUTI, TATA;
    }
}

以下是运行main()的输出。

代码语言:javascript
复制
{pin-1=HONDA, dl-1=HONDA}
{pin-2=TATA, pin-1=HONDA, dl-2=TATA, dl-1=HONDA}
{pin-2=TATA, dl-3=TOYOTA, pin-1=HONDA, dl-2=TATA, dl-1=HONDA}

关于这个设计的一些要点:

当遇到现有的键时,它不会抛出异常,只是忽略它。

  • 如果我们需要键中的各种类型,那么我们可能不得不使用Map<Object, Car>.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69860616

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档