Нужна карта / таблица Java с несколькими ключами к одному значению. Значение обычно изменяется - PullRequest
11 голосов
/ 06 августа 2009

Мне нужна коллекция, которая позволяет нескольким ключам получать доступ к одному объекту.

Мне нужно применить частые изменения к этому объекту.

Это также должно быть эффективно для 500k + записей.

Ответы [ 5 ]

19 голосов
/ 06 августа 2009

Любая реализация java.util.Map<K,V> сделает это - есть без ограничений на сколько раз конкретное значение может быть добавлено под отдельными ключами:

Map<String,Integer> m = new HashMap<String, Integer>();
m.put("Hello", 5);
m.put("World", 5);
System.out.println(m); // { Hello->5, World->5 }  

Если вам нужна карта, в которой один ключ связан с несколькими значениями, она называется multi-map , и вы можете получить ее из API Google java collection * или из Общие коллекции Apache

5 голосов
/ 06 августа 2009

Ммм ...

Map map = new HashMap();
Object someValue = new Object();
map.put(new Object(), someValue);
map.put(new Object(), someValue);

Теперь карта содержит одно и то же значение дважды, доступное через разные ключи. Если это не то, что вы ищете, вы должны переработать свой вопрос. :)

3 голосов
/ 18 июня 2010

Я как бы по-разному истолковал его просьбу. Что делать, если нужно, чтобы два совершенно разных набора ключей имели доступ к одним и тем же базовым значениям. Например:

    "Hello"    ------|
                     |----> firstObject
       3       ------|

    "Monkey"   ------|
                     |----> secondObject
       72      ------|

       14      -----------> thirdObject

   "Baseball"  ------|
                     |----> fourthObject
       18      ------|

Очевидно, что наличие двух карт, одной для целочисленных ключей и одной для ключей String, работать не будет, поскольку обновление одной карты не будет отражаться на другой карте. Предположим, вы изменили Map<String,Object>, обновив «Обезьяна», чтобы отобразить на 1stObject. Результатом этой модификации является изменение Entry<String,Object> в пределах этой карты, но это, конечно, не влияет на другую карту. Итак, в то время как вы хотели:

    "Monkey"   ------|
                     |----> fifthObject
       72      ------|

то, что вы получили бы на самом деле, было бы так:

    "Monkey"   -----------> fifthObject

       72      -----------> secondObject

что я делаю в этой ситуации, так это наличие двух карт рядом друг с другом, но вместо того, чтобы заставить их сказать Map<String, Integer>, я бы сделал их Map<String, Integer[]>, где связанный массив представляет собой массив из одного члена. В первый раз, когда я связываю ключ со значением, если массив еще не существует и ключ возвращает ноль, я создаю массив и связываю с ним любой другой ключ (в карте этого ключа). Впоследствии я изменяю только содержимое массива, но не ссылку на сам массив, и это работает очаровательно.

    "Monkey"   -------> fifthObjectArray ------|
                                               |-----> fifthObjectArray[0]
       72      -------> fifthObjectArray ------|
3 голосов
/ 06 августа 2009

это может делать то, что вы хотите:

import java.util.*;
class Value {
    public String toString() {
        return x.toString();
    }
    Integer x=0;
}
public class Main {
    public static void main(String[] arguments) {
        Map m=new HashMap();
        final Value v=new Value();
        m.put(1,v);
        m.put(2,v);
        System.out.println(m.get(1));
        System.out.println(m.get(2));
        v.x=42;
        System.out.println(m.get(1));
        System.out.println(m.get(2));
    }
0 голосов
/ 01 ноября 2014

Твой вопрос на самом деле заставил меня задуматься о том, чтобы сделать этот урок для такой вещи. В настоящее время я работаю над движком 2D-игр, и ваш вопрос полностью заставил меня задуматься о том, что мне нужно.

Кстати, как вы это сформулировали, я верю, что вы хотите;

Объект, который содержит ключи и значения, но вы также можете получить значения общих ключей (я использую этот объект специально для сокращения ЦП за счет использования чуть больше памяти.)

Этот класс 'Тип K является типом первичного ключа. Тип T - это тип значения HashSet.

Способ реализации и использования этого объекта:

MapValueSet<ObjectType1,ObjectType2> mainmap = new  

MapValueSet<ObjectType1,ObjectType2>()
HashSet<Integer> tags = new HashSet<Integer>();
       public void test(){
            ObjectType1 = new ObjectType1();
            ObjectType2 = new ObjectType2();

            tags.add(mainmap.put(ObjectType1,ObjectType2);
            mainmap.get(ObjectType1,Integer);
       } 

Вам нужно будет хранить уникальные теги в наборе или массиве в любом классе, который вы реализуете, потому что если бы вы этого не делали, вы бы хранили сущности и не знали, какой из них был каким. Поэтому сохраните целое число, полученное от метода put (), в массив или набор и выполните итерацию по нему.

Вы можете проверить значения этого Класса, если они существуют, или для каких ключевых объектов установлено значение.

Вот класс MapValueSet;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

public class MapValueSet<K,T> {

        Indexer indxK = new Indexer();
        Indexer indxT = new Indexer();

        Map<K,Integer> kTags = new HashMap<K,Integer>();
        Map<T,Integer> tTags = new HashMap<T,Integer>();

        Map<Integer,HashSet<Integer>> MapK = new HashMap<Integer,HashSet<Integer>>();

        Map<Integer,HashSet<Integer>> MapT = new HashMap<Integer,HashSet<Integer>>();

public int put(K k, T t){
    int tag = -1;
    if(!kTags.containsKey(k)){
        kTags.put(k, indxK.getNextTag());
    }

    if(!MapK.containsKey(kTags.get(k))){
        MapK.put(kTags.get(k), new HashSet<Integer>()); 
    }

    if(!tTags.containsKey(t)){
        tTags.put(t, tag = indxT.getNextTag());
    }

    if(!MapT.containsKey(tTags.get(t))){
        MapT.put(tag = tTags.get(t), new HashSet<Integer>());
    }       
        MapK.get(kTags.get(k)).add(tTags.get(t));
        MapT.get(tag = tTags.get(t)).add(kTags.get(k)); 

    return tag;
}

       @SuppressWarnings("unchecked")
         public T get(K k, int tag){
            Object[] tArr = tTags.keySet().toArray();
            for(int i = 0; i < tArr.length; i++){
              if(tTags.get((T)tArr[i])== tag){
                    return (T)tArr[i];
             }
           }
           return null;
        }

        public boolean removeAtKey(K k, T t){
                int kTag = -1;
                int tTag = -1;

                if(kTags.get(k) != null){
                kTag = kTags.get(k);
                }

                if(tTags.get(t) != null){
                tTag = tTags.get(t);
                }

                if(kTag == -1 || tTag == -1){
                        System.out.println("Keys are Blank at: removeAtKey(k,t)");
                        return false;
                }

                boolean removed = false;

                        if(MapK.get(kTag) != null){
                                removed = MapK.get(kTag).remove(tTag);
                        }
                        if(MapT.get(tTag) != null){
                                MapT.get(tTag).remove(kTag);
                        }

                        if(!MapK.containsKey(kTag)){
                                kTags.remove(k);
                                indxK.removeTag(kTag);
                        }

                        if(MapK.containsKey(kTag)){
                                tTags.remove(t);
                                indxT.removeTag(tTag); 

                        }

                return removed;
        }

        public void removeAtValue(T t){
                if(!tTags.containsKey(t)){
                        return;
                }
                Object[] keyArr = MapT.get(tTags.get(t)).toArray();

                for(int i = 0; i < keyArr.length; i++){
                        MapK.get(keyArr[i]).remove(tTags.get(t));
                }

                        indxT.removeTag(tTags.get(t));
                        MapT.remove(tTags.get(t));
                        tTags.remove(t);
        }

        public boolean mapContains(T t){
                if(tTags.get(t) == null){
                        return false;
                }
                int tTag = tTags.get(t);

                return MapT.get(tTag) != null && !MapT.get(tTag).isEmpty();
        }

        public boolean containsKey(K k){

                if(kTags.get(k) == null){
                        return false;
                }

                return MapK.containsKey(kTags.get(k));
        }

        public boolean keyContains(K k, T t){

                if(kTags.get(k) != null && tTags.get(t) != null){
                        return MapK.get(kTags.get(k)).contains(tTags.get(t));
                }

                return false;

        }

        @Override
        public String toString(){

                String s = "";

                s = s+ "Key      Map: " + MapK.toString() + "\n";
                s = s+ "Value    Map: " + MapT.toString() + "\n";
                s = s+ "KeyTag   Map: " + kTags.toString() + "\n";
                s = s+ "ValueTag Map: " + tTags.toString() + "\n";
                s = s+ "KeyTag   List: " + indxK.activeSet().toString() + "\n";
                s = s+ "ValueTag List: " + indxT.activeSet().toString();

                return s;              
        }


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