需要一个具有多个键到一个值的 Java 映射/表。价值通常被改变

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1237581/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 01:14:20  来源:igfitidea点击:

Need a Java map/table with multiple keys to one value. Value is commonly altered

javacollectionshashmap

提问by Duncan

What I need is a collection which allows multiple keys to access a single object.

我需要的是一个允许多个键访问单个对象的集合。

I need to apply frequent alterations to this object.

我需要经常修改这个对象。

It also must be efficient for 500k+ entries.

对于 500k+ 条目,它也必须是有效的。

采纳答案by oxbow_lakes

Any implementation of java.util.Map<K,V>will do this - there is no restrictionon how many times a particular value can be added under separate keys:

的任何实现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 }  

If you want a map where a single key is associated with multiple values, this is called a multi-mapand you can get one from the google java collections APIor from Apache's commons-collections

如果您想要一个地图,其中一个键与多个值相关联,这称为多地图,您可以从google java collections APIApache 的 commons-collections获取一个

回答by Bombe

Uhm…

嗯…

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

Now the map contains the same value twice, accessible via different keys. If that's not what you're looking for you should rework your question. :)

现在地图包含两次相同的值,可通过不同的键访问。如果这不是您要查找的内容,则应该重新处理您的问题。:)

回答by Ray Tayek

this maydo what you want:

可能会做你想做的:

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));
    }

回答by fragorl

I sort of interpreted his request differently. What if one wants two completely different keysets to access the same underlying values. For example:

我对他的要求有不同的解释。如果想要两个完全不同的键集访问相同的底层值怎么办。例如:

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

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

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

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

Obviously having two maps, one for the integer keys and one for the String keys, isn't going to work, since an update in one map won't reflect in the other map. Supposing you modified the Map<String,Object>, updating "Monkey" to map to fifthObject. The result of this modification is to change the Entry<String,Object>within that map, but this of course has no effect on the other map. So whilst what you intended was:

显然有两个映射,一个用于整数键,一个用于字符串键,是行不通的,因为一个映射中的更新不会反映在另一个映射中。假设您修改了Map<String,Object>,更新“Monkey”以映射到第五对象。这个修改的结果是改变了Entry<String,Object>那张地图内的,但这当然对另一张地图没有影响。所以虽然你的意图是:

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

what you'd get in reality would be this:

你在现实中得到的是这样的:

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

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

what I do in this situation is to have the two side by side maps, but instead of making them say Map<String, Integer>I would make them Map<String, Integer[]>, where the associated array is a single member array. The first time I associate a key with a value, if no array exists yet and the key returns null, I create the array, and associate any other key I wish to with it (in that key's map). Subsequently, I only modify the array's contents, but never the reference to the array itself, and this works a charm.

在这种情况下,我所做的是让两个并排映射,而不是让他们说Map<String, Integer>我会制作它们Map<String, Integer[]>,其中关联的数组是单个成员数组。我第一次将键与值关联时,如果尚不存在数组并且键返回 null,我会创建该数组,并将我希望与之关联的任何其他键(在该键的映射中)关联起来。随后,我只修改数组的内容,但从不修改对数组本身的引用,这很有魅力。

    "Monkey"   -------> fifthObjectArray ------|
                                               |-----> fifthObjectArray[0]
       72      -------> fifthObjectArray ------|

回答by Mice

Your Question actually got me thinking of making this class to handle such a thing. I am currently working on a 2D game engine and your question completely made me think of exactly what I needed.

你的问题实际上让我想到让这个类来处理这样的事情。我目前正在研究 2D 游戏引擎,你的问题完全让我想到了我需要什么。

By the way you've worded it, I believe what you want is;

顺便说一句,我相信你想要的是;

An object that holds keys and values, but you can also get the common keys values hold (I use this object specifically to cut down on cpu at the cost of using just a little more memory.)

一个保存键和值的对象,但你也可以得到常用的键值(我专门使用这个对象来减少 CPU 消耗,代价是使用更多的内存。)

This Class' The K type is the Primary Key type. The T type is the HashSet Value Type.

The way you implement and use this object is:

这个Class' K 类型是Primary Key 类型。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);
       } 

You will need to hold the unique tags in a set or arraylist in any class you implement this because if you didn't you'd be storing entities and not know which one was which. So store the integer you get from the put() method into an arraylist or set, and iterate through that.

您将需要在您实现此功能的任何类中将唯一标签保存在集合或数组列表中,因为如果不这样做,您将存储实体而不知道哪个是哪个。因此,将从 put() 方法获得的整数存储到数组列表或集合中,并遍历它。

You can check this Class's values if they exist, or which key objects the value is set to.

您可以检查此类的值是否存在,或者该值设置为哪些键对象。

Here is the Class MapValueSet;

这是类 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;              
        }


}