MultiKeyMap получить метод - PullRequest
       9

MultiKeyMap получить метод

6 голосов
/ 28 ноября 2011

Я хочу использовать MultiKeyMap из Apache Collection, потому что мне нужен HashMap с двумя ключами и значением. Чтобы положить элементы я делаю это:

private MultiKeyMap multiKey = new MultiKeyMap();
multiKey.put("key1.1", "key2.1", "value1");

И для элемента get я делаю это:

String s = multiKey.get("key1.1");

Но String s приходит null ... Если я передам два ключа, вот так:

String s = multiKey.get("key1.1", "key2.1");

String s поставляется со значениями value1 ...

Как я могу расширить MultiKeyMap, чтобы получить правильное значение, когда я передаю только одну из двух клавиш ?

Ответы [ 9 ]

5 голосов
/ 28 ноября 2011

Если вы укажете значение двумя ключами, вам понадобятся оба ключа, чтобы вернуть его. Хеш-функция не предназначена для возврата всех возможных значений, связанных только с одним из двух ключей. Для этого может потребоваться найти другую структуру данных.

4 голосов
/ 28 ноября 2011

Если вам нужен только один ключ для получения значения, у вас есть простой старый HashMap.

private Map<String, String> map = new HashMap<>();

map.put("key1.1", "value1");
map.put("key2.1", "value1");

А для элемента get вы можете сделать это:

String s = map.get("key1.1"); // s == "value1"

MultiKeyMap требуетсякогда оба ключа должны быть предоставлены.

1 голос
/ 28 ноября 2011

Я не знаю точного решения вашей проблемы. Но я предлагаю вам реализовать это как:

Map<K2, K1> m2;
Map<K1, V>  m1;

И см .: Как реализовать Карту с несколькими ключами?

1 голос
/ 28 ноября 2011

Похоже, вам просто не нужен MultiKeyMap.Вам нужна обычная карта.Используя его, вы можете связать одно и то же значение с любым количеством ключей.

Map<String, String> map = new HashMap<String, String>();
Object value = .....
map.put("key1", value);
map.put("key2", value);

..................

if(map.get("key1") == map.get("key2")) {
    System.out.println("the same value stored under 2 different keys!");
}
1 голос
/ 28 ноября 2011

MultiKeyMap - это использование кортежей в качестве ключей, а не сопоставление одного значения более чем одному ключу.Используйте карту нормалей и просто введите свое значение дважды, используя разные ключи.

При удалении значений требуется некоторая осторожность.Когда вы удаляете значение для первого ключа, хотите ли вы автоматически удалить другие ключи с таким же значением?Если это так, вам нужно либо перебрать все ключи и вручную удалить их с одинаковым значением, что может быть неэффективно, либо сохранить какую-то обратную карту для быстрого поиска ключей для определенного значения.

0 голосов
/ 13 мая 2017

Вот простая реализация MultiKeyMap, которая сработала для меня.

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

public class MultiMap<K, V> implements Map<K, V>
{
    private class MultiMapEntery implements java.util.Map.Entry<K, V>
    {
        private final K key;
        private V value;

        public MultiMapEntery(K key, V value)
        {
            this.key = key;
            this.value = value;
        }
        @Override
        public K getKey()
        {
            return key;
        }

        @Override
        public V getValue()
        {
            return value;
        }

        @Override
        public V setValue(V value)
        {
            V oldValue = this.value;
            this.value = value;
            return oldValue;
        }
    };

    private final Map<K, String> keyMap = new HashMap<K, String>();
    private final Map<String, Set<K>> inverseKeyMap = new HashMap<String, Set<K>>();
    private final Map<String, V> valueMap = new HashMap<String, V>();

    @Override
    public void clear()
    {
        keyMap.clear();
        inverseKeyMap.clear();
        valueMap.clear();
    }

    @Override
    public boolean containsKey(Object key)
    {
        return keyMap.containsKey(key);
    }

    @Override
    public boolean containsValue(Object value)
    {
        return valueMap.containsValue(value);
    }

    @Override
    public Set<java.util.Map.Entry<K, V>> entrySet()
    {
        Set<java.util.Map.Entry<K, V>> entries = new HashSet<>();
        for(K key : keyMap.keySet())
        {
            V value = valueMap.get(key);
            entries.add(new MultiMapEntery(key, value));
        }
        return entries;
    }

    @Override
    public V get(Object key)
    {
        return valueMap.get(keyMap.get(key));
    }

    @Override
    public boolean isEmpty()
    {
        return valueMap.isEmpty();
    }

    @Override
    public Set<K> keySet()
    {
        return keyMap.keySet();
    }

    @Override
    public V put(K key, V value)
    {
        String id = keyMap.get(key);
        if(id == null)
        {
            id = UUID.randomUUID().toString();
        }
        keyMap.put(key, id);
        Set<K> keys = inverseKeyMap.get(id);
        if(keys == null)
        {
            keys = new HashSet<>();
        }
        keys.add(key);
        inverseKeyMap.put(id, keys);
        valueMap.put(id, value);
        return value;
    }

    public V put(Set<K> keys, V value)
    {
        String id = null;
        for(K key : keys)
        {
            id = keyMap.get(key);
            if(id != null) // one of the keys already exists
            {
                break;
            }
        }

        if(id == null)
        {
            id = UUID.randomUUID().toString();
        }

        for(K key : keys)
        {
            keyMap.put(key, id);
        }
        inverseKeyMap.put(id, keys);
        valueMap.put(id, value);
        return value;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> map)
    {
        for(java.util.Map.Entry<? extends K, ? extends V> entry : map.entrySet())
        {
            put(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public V remove(Object key)
    {
        String id = keyMap.get(key);
        keyMap.remove(key);
        Set<K> keys = inverseKeyMap.get(id);
        keys.remove(key);
        V value = valueMap.get(id);
        if(keys.size() == 0) // it was the last key, now remove the value
        {
            valueMap.remove(id);
        }
        return value;
    }

    @Override
    public int size()
    {
        return valueMap.size();
    }

    @Override
    public Collection<V> values()
    {
        return valueMap.values();
    }

    public static void main(String[] args)
    {
        MultiMap<String, String> m = new MultiMap<>();
        m.put("a", "v1");
        Set<String> s = new HashSet<>();
        s.add("b");
        s.add("c");
        s.add("d");
        m.put(s, "v2");

        System.out.println("size:"  + m.size());
        System.out.println("keys:"  + m.keySet());
        System.out.println("values:"  + m.values().toString());
        System.out.println("a:" + m.get("a"));
        System.out.println("b:" + m.get("b"));
        System.out.println("c:" + m.get("c"));
        System.out.println("d:" + m.get("d"));

        m.remove("a");

        System.out.println("size:"  + m.size());
        System.out.println("keys:"  + m.keySet());
        System.out.println("values:"  + m.values().toString());
        System.out.println("a:" + m.get("a"));
        System.out.println("b:" + m.get("b"));
        System.out.println("c:" + m.get("c"));
        System.out.println("d:" + m.get("d"));

        s.add("a");
        m.put(s, "v3");

        System.out.println("size:"  + m.size());
        System.out.println("keys:"  + m.keySet());
        System.out.println("values:"  + m.values().toString());

        System.out.println("a:" + m.get("a"));
        System.out.println("b:" + m.get("b"));
        System.out.println("c:" + m.get("c"));
        System.out.println("d:" + m.get("d"));
    }
}
0 голосов
/ 16 декабря 2016

Я бы предложил создать отдельный класс для нескольких ключей:

public class Test {

Map<Shape, Book> test1 = new HashMap<>();
Book book = new Book("A");
test1.put(Shape, book);


private class Shape {
  String id1;
  String id2;
public Shape(String id1, String id2) {
  this.id1 = id1;
  this.id2 = id2;
}
 @Override
 public boolean equals(Object o) {//}
@Override
public int hashCode() {//}
}

}
0 голосов
/ 18 апреля 2013

Вместо этого вы можете использовать данные табличных данных из гуавы.

0 голосов
/ 28 ноября 2011

Вы просто не можете, так как MultiKeyMap работает не так.Поместите значение с отдельными ключами, а затем попробуйте получить его для каждого ключа за раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...