我需要的是一个允许多个键访问单个对象的集合。
我需要经常更改此对象。
对于500k +条目,它也必须有效。
答案 0 :(得分:18)
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 }
如果您想要一个地图,其中一个键与多个值相关联,这称为多地图,您可以从google java collections API或{{3}获取一个}
答案 1 :(得分:5)
...嗯
Map map = new HashMap();
Object someValue = new Object();
map.put(new Object(), someValue);
map.put(new Object(), someValue);
现在地图包含两次相同的值,可通过不同的键访问。如果这不是你想要的,你应该重写你的问题。 :)
答案 2 :(得分:3)
这个可以做你想做的事:
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));
}
答案 3 :(得分:3)
我有点不同地解释他的要求。如果想要两个完全不同的键集来访问相同的基础值,该怎么办?例如:
"Hello" ------|
|----> firstObject
3 ------|
"Monkey" ------|
|----> secondObject
72 ------|
14 -----------> thirdObject
"Baseball" ------|
|----> fourthObject
18 ------|
显然有两个映射,一个用于整数键,一个用于String键,因为一个映射中的更新不会反映在另一个映射中。假设您修改了Map<String,Object>
,更新了“Monkey”以映射到fifthObject。此修改的结果是更改该地图中的Entry<String,Object>
,但这当然对其他地图没有影响。所以你想要的是:
"Monkey" ------|
|----> fifthObject
72 ------|
你现实中得到的是:
"Monkey" -----------> fifthObject
72 -----------> secondObject
我在这种情况下做的是拥有两个并排的地图,但不是让他们说Map<String, Integer>
而是让它们Map<String, Integer[]>
,其中关联的数组是单个成员数组。我第一次将一个键与一个值相关联,如果还没有数组,并且该键返回null,我创建该数组,并将我想要的任何其他键与它相关联(在该键的映射中)。随后,我只修改数组的内容,但从不引用数组本身,这就是一个魅力。
"Monkey" -------> fifthObjectArray ------|
|-----> fifthObjectArray[0]
72 -------> fifthObjectArray ------|
答案 4 :(得分:0)
你的问题实际上让我想到让这堂课来处理这样的事情。我目前正在研究2D游戏引擎,你的问题让我完全想到了我需要的东西。
顺便说一下,我相信你想要的是;
一个包含键和值的对象,但你也可以保持公共键值(我特意使用这个对象来减少cpu,但代价是只需要多一点内存。)
此类'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);
}
你需要在你实现它的任何类中的set或arraylist中保存唯一标记,因为如果你没有,你将存储实体而不知道哪个是哪个。因此,将从put()方法获得的整数存储到arraylist或set中,然后遍历它。
您可以检查此类的值(如果存在),或者将值设置为哪些关键对象。
这是Class 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;
}
}