Java数据结构将多个键映射到同一个值

Java数据结构将多个键映射到同一个值,java,data-structures,Java,Data Structures,在Java中,我正在寻找一种将多个键映射到同一个值的方法。假设我将数字0-9作为键,“x”、“y”和“z”作为值,如下所示: 0->y 1->y 2->y 3->x 4->x 5->y 6->z 7->y 8->z 9->z 现在x,y和z都是很长的字符串,我有数百万个键,所以我不能多次存储字符串。你会怎么做 我的一个想法是创建两个数组:生成一个人工的第二个键,原始键映射到该数组,而另一个数组中的第二个键是实际值的键。这样,值只存储一

在Java中,我正在寻找一种将多个键映射到同一个值的方法。假设我将数字0-9作为键,“x”、“y”和“z”作为值,如下所示:

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
x->{3, 4}
y->{0, 1, 2, 5, 7}
z->{6, 8, 9}

但问题是:有更好的数据结构吗?

我不太理解这个问题。如果您有一个字符串数组:
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;
//...
任何
Map
都可以-您只存储对字符串的引用,而不是它的副本,因此不管它有多长


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

为什么不反转键/值配对?对值使用集合或数组:

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
x->{3, 4}
y->{0, 1, 2, 5, 7}
z->{6, 8, 9}

Java将自动为您合并字符串引用,因此您不需要手动进行合并以节省内存。你可以把键/值放在HashMap中。

如果你不喜欢Pete Kirkham的建议(这是最好的方法,IMO),你可以使用Google Collections(呃…现在)。

每个映射条目将使用几百位来表示一个理论上可以保存在2中的值

如果键的密度大于每几百个整数中1的数量级,那么完全不使用映射,而是使用一个数组(类似于a),其中字节值映射到字符串,会更快、更小。如果您想获得4倍以上的密度,请将4个值打包到一个字节中


这只在你有大量数据时才有意义,但你说有数百万个键,所以我认为这很合适。

这不是真的。如果它是一个文本,编译器将插入字符串,以便用相同的字符串对象替换相等的文本,并且您可以手动调用
intern()
,但Java在运行时永远不会隐式/自动执行这些操作。一旦你有了一个对字符串的引用,Java就不会改变这个引用来指向幕后的其他字符串,而且你总是可以使用
new
关键字得到同一字符串的唯一实例。例如,对于从输入流或用户输入读取的字符串,这些都不会发生。我还打算建议使用MultiMap,但他正在寻找多个键映射到相同的值,而不是相反的值。Pete,这很公平。我真的没有时间写一篇论文,所以我刚刚删除了评论。答案肯定是正确的,但如果不必
映射,就可以把(k,v)
放在重复的值上吗?做一些像map.put(k1,k2,…,kn,v)这样的事情会很好。