Java map : alias on key

标签 java dictionary key alias

是否存在可以在现有键上添加别名的映射实现

SuperMap map = .....;
map.put("key1" , object1);
map.addAlias("key1" , "aliaskey"); // <== create alias
Object o = map.get("aliaskey"); // equals object1

谢谢

最佳答案

不确定你想用它做什么,或者它是否值得麻烦,但到目前为止我在这个线程中看到的实现都存在别名与它作为别名的 key 断开连接的问题。例如,如果您说:

SuperMap<String, String> sm = new SuperMap<String, String>();
sm.put("Elvis", "Presley");

sm.addAlias("Priscilla", "Elvis");
System.out.println(sm.get("Elvis"));
System.out.println(sm.get("Priscilla"));

sm.put("Elvis", "Costello");
System.out.println(sm.get("Elvis"));
System.out.println(sm.get("Priscilla"));

你会得到:

Presley
Presley
Costello
Presley

(注意:这是 SuperMap 的原始实现,而不是编辑后的版本。)

如果你想要一个真正的别名——如果你想得到 Presley, Presley, Costello, Costello——你将需要一些更复杂的东西。

下面的代码未经测试(整个企业看起来有点疯狂),但类似的东西应该可以工作:

public class AliasMap<K, V> extends AbstractMap<K, V>
{
    private final Map<K, V> backingMap;
    private final Map<K, K> aliasToRealKey;

    public AliasMap ()
    {
        this( new HashMap<K, V>() );
    }

    public AliasMap ( Map<K, V> backingMap )
    {
        this.backingMap = backingMap;
        aliasToRealKey = new HashMap<K, K>();
    }

    @Override
    public Set<Entry<K, V>> entrySet ()
    {
        return new AliasAwareEntrySet<K, V>( aliasToRealKey, backingMap );
    }

    @Override
    public V put ( K k, V v )
    {
        if ( aliasToRealKey.containsKey( k ) )
        {
            throw new IllegalArgumentException( "An alias '" + k + "' already exists in the map" );
        }
        return backingMap.put( k, v );
    }

    @Override
    public V get ( Object o )
    {
        V v = backingMap.get( o );
        if ( v == null )
        {
            K realKey = aliasToRealKey.get( o );
            if ( realKey == null )
            {
                return null;
            }
            return backingMap.get( realKey );
        }
        return v;
    }

    public void alias ( K realKey, K alias )
    {
        if ( backingMap.containsKey( alias ) )
        {
            throw new IllegalArgumentException( "The key '" + alias + "' already exists in the map" );
        }
        aliasToRealKey.put( alias, realKey );
    }

    private static class AliasAwareEntrySet<K, V> extends AbstractSet<Entry<K, V>>
    {
        private Map<K, K> aliasToRealKey;
        private Map<K, V> backingMap;

        public AliasAwareEntrySet ( Map<K, K> aliasToRealKey, final Map<K, V> backingMap )
        {
            this.aliasToRealKey = aliasToRealKey;
            this.backingMap = backingMap;
        }

        @Override
        public Iterator<Entry<K, V>> iterator ()
        {
            return new AliasAwareEntryIterator<K, V>( backingMap, aliasToRealKey );
        }

        @Override
        public int size ()
        {
            return backingMap.size() + aliasToRealKey.size();
        }

    }

    private static class AliasAwareEntryIterator<K, V> implements Iterator<Entry<K, V>>
    {
        Set<Entry<K, V>> realEntries;
        Set<K> aliasKeys;
        Iterator<Entry<K, V>> realIterator;
        Iterator<K> aliasIterator;

        boolean isRealEntry = true;
        private Map<K, V> backingMap;
        private Map<K, K> aliasToRealKey;

        public AliasAwareEntryIterator ( final Map<K, V> backingMap, Map<K, K> aliasToRealKey )
        {
            this.realEntries = backingMap.entrySet();
            this.aliasKeys = aliasToRealKey.keySet();

            realIterator = realEntries.iterator();
            aliasIterator = aliasKeys.iterator();
            this.backingMap = backingMap;
            this.aliasToRealKey = aliasToRealKey;
        }

        public boolean hasNext ()
        {
            return realIterator.hasNext() || aliasIterator.hasNext();
        }

        public Entry<K, V> next ()
        {
            if ( realIterator.hasNext() )
            {
                return realIterator.next();
            }
            isRealEntry = false;

            final K alias = aliasIterator.next();
            final K realKey = aliasToRealKey.get( alias );
            return new AliasAwareEntry( alias, realKey );
        }

        public void remove ()
        {
            if ( isRealEntry )
            {
                realIterator.remove();
            }
            else
            {
                aliasIterator.remove();
            }
        }

        private class AliasAwareEntry implements Entry<K, V>
        {

            private final K alias;
            private final K realKey;

            public AliasAwareEntry ( K alias, K realKey )
            {
                this.alias = alias;
                this.realKey = realKey;
            }

            public K getKey ()
            {
                return alias;
            }

            public V getValue ()
            {
                return backingMap.get( realKey );
            }

            public V setValue ( V v )
            {
                return backingMap.put( realKey, v );
            }
        }
    }

    public static void main ( String[] args )
    {
        AliasMap<String, String> sm = new AliasMap<String, String>();
        sm.put( "Elvis", "Presley" );

        sm.alias( "Elvis", "Priscilla" );
        System.out.println( sm.get( "Elvis" ) );
        System.out.println( sm.get( "Priscilla" ) );

        sm.put( "Elvis", "Costello" );
        System.out.println( sm.get( "Elvis" ) );
        System.out.println( sm.get( "Priscilla" ) );

        for ( String s : sm.keySet() )
        {
            System.out.println(s);
        }

        for ( Iterator<Entry<String, String>> iterator = sm.entrySet().iterator(); iterator.hasNext(); )
        {
            Entry<String, String> entry = iterator.next();
            System.out.println( entry.getKey() + " : " + entry.getValue() );
            if ( "Priscilla".equals( entry.getKey() ) )
            {
                iterator.remove();
            }
        }

        for ( String s : sm.keySet() )
        {
            System.out.println(s);
        }
    }
}

关于Java map : alias on key,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15486884/

相关文章:

java - 如何在代码中动态添加 Java Agents jar 后卸载它们? Java 检测

java - 具有自定义身份验证的 Firebase Java 客户端

java - SQLiteException : no such table 的问题

ios - 如何在 Swift 中创建和访问 NSDictionary

ios - 不能为类型值添加下标

Ruby - 将两个散列与一些类似的键合并

Java套接字通信问题

Python-附加到字典中的列表

json - jq:选择并删除嵌套字段

dictionary - map[gorm.DB]struct{}{} 给出无效的映射键类型 gorm.DB