2010-06-15 50 views
6

在Java中,我正在寻找一种将多个键映射到相同值的方法。比方说,我有数字0-9的按键,而“x”,“y”和“Z”的值如下:用于将多个键映射到相同值的Java数据结构

0->y 
1->y 
2->y 
3->x 
4->x 
5->y 
6->z 
7->y 
8->z 
9->z 

现在x,y和z是很长的字符串,我有数百万个密钥,所以我无法多次存储这些字符串。你会怎么做呢?

我想到的一个想法是创建两个数组:生成一个人为的第二个键,将原始键映射到该键,而另一个数组中的键是实际值的关键。这样,该值仅存储一次和原始关键仍然可以间接地映射到值:

0->k1 
1->k1 
2->k1 
3->k2 
4->k2 
5->k1 
6->k3 
7->k1 
8->k3 
9->k3 

k1->y 
k2->x 
k3->z 

问题,但:有没有更好的数据结构呢?

回答

19

任何Map<Integer,String>会做的 - 你只存储到字符串,而不是它的一个副本的引用,所以没关系它有多长。

如果您要多次构建相同的字符串值,请使用intern()每次都为该值获取相同的String对象。

+0

这很有道理。谢谢。 – eikes 2010-06-15 15:32:07

+3

+1 for'intern()' – 2010-06-15 23:07:17

+0

皮特,够公平的。我真的没有时间写一篇论文,所以我刚刚删除了评论。 – 2010-06-17 21:52:42

1

我真的不明白这个问题。如果你有一个字符串数组:String[] arr然后只是设置不同的索引到同一个对象 - 也就是使引用相同。

String[] map = new String[10]; 
String x = "foo"; 
String y = "bar"; 
String z = "baz"; 
map[0] = x; 
map[1] = y; 
map[2] = x; 
//... 
2

为什么不反转键/值配对?使用设置或数组变量的值:

x->{3, 4} 
y->{0, 1, 2, 5, 7} 
z->{6, 8, 9} 
-1

Java将自动巩固字符串引用了你,所以你不需要做手工,以节省内存。您可以将键/值放在HashMap中。

+1

这不是事实。如果它是一个字面值,编译器将实习字符串,以便相同的字面值被相同的String对象替换,并且可以手动调用intern(),但Java永远不会在运行时隐式/自动执行任何操作。一旦你有一个字符串的引用,Java不会将该引用改为指向幕后的其他引用,并且可以使用'new'关键字始终拥有相同字符串的唯一实例。因此,例如,对于从输入流或用户输入读取的字符串而言,没有发生这种情况。 – 2010-06-15 15:33:08

1

如果你不喜欢Pete Kirkham的建议(这将是最好的方式,IMO),你可以使用Google Collections(er ... Guava现在)MultiMap

+4

我打算建议MultiMap,但他正在寻找多个映射到相同值而不是相反的键。 – Stevko 2010-06-15 15:34:33

0

每个映射条目将使用几百位代表在理论上可以保持在2

如果密钥不低于每几百整数1的订单上的数量更加密集的值,这将是更快,更小,根本不使用地图,而是一个数组 - 像Trove TByteArrayList - 其中字节值映射到您的字符串。如果您想要获得4倍以上的密度,请将4个值组合成一个字节。

这只有在你得到大量数据时才有意义 - 但是你说了数百万个密钥,所以我认为它很合适。

相关问题