我有一张地图。键包含6个字符的String和Properties类,大致如下所示:
public class Properties {
private String propertyOne;
private String propertyTwo;
private String propertyThree;
private String propertyFour;
...
...
}
现在假设我在地图中有一些条目如下:
41111 - > {1,2,3,4,5}
41112 - > {1,2,3,4,6}
41234 - > {1,2,345,87,65}
51123 - > {100,200,30000,345,123}
51122 - > {100,200,30000,556,989}
现在,如果我map.get("12567")
,我会得到所需的属性对象。
我遇到的挑战是,我必须创建一个可以保存部分数据的数据结构。根据部分数据,我的意思是,如果我map.get("4111")
我应该得到{1,2,3,4,5}
(41111的属性)和{1,2,3,4,6}
<的交叉点 strong>(41112的属性),{1,2,3,4,null}.
同样map.get("41")
应生成{1,2,null,null,null}
。
我现在有一个解决方案,即我创建了多个HashMaps,其中包含所有可能的部分键及其对应的值,如:
Map<String, Property>`` keyValuesForOneChar
包含所有可能的单个字符作为键及其对应的值。
Map<String, Property> keyValuesForTwoChars
包含所有可能的两个字符作为键及其对应的值。
我不喜欢这个解决方案,因为它非常直接,我不认为维护多个哈希图是个好主意。还有一个问题是我的原始数据计数大约是200000,并且所有排列组合我将创建巨大的部分数据,并且我认为哈希映射的性能会降低。请为此问题提出更好的解决方案。我有以下限制:
答案 0 :(得分:4)
HashMap绝对不是最适合您问题的数据结构。由于您的键是字符串,您可以实现一个trie(也称为前缀树)。
它的工作原理是将字符串键拆分成较小的字符串或字符。这样,您可以存储键的值,也可以存储公共前缀。也就是说,你可以存储&#34; 41111&#34;和&#34; 41112&#34;在公共前缀&#34; 4111&#34;。当查找4111时,需要O(m)步,其中m是键的长度,并且您将能够检索{1,2,3,4,5}和{1,2,3的交集。 ,4,6}如果在trie中插入项目时更新交叉点。
检索部分属性
您可以在构建trie时更新部分属性。让我们说你插入这对夫妇(41111,{1,2,3,4,5})。尝试是特定的树,它看起来像这样。符号k,v
表示这是一个键为k
且值为v
的节点。
4,{1,2,3,4,5}
|
1,{1,2,3,4,5}
|
1,{1,2,3,4,5}
|
1,{1,2,3,4,5}
|
1,{1,2,3,4,5}
在路径上的每个节点上,存储部分属性。现在,当插入这对夫妇(41112,{1,2,3,4,6})时,你更新了trie:
4,{1,2,3,4,null}
|
1,{1,2,3,4,null}
|
1,{1,2,3,4,null}
|
1,{1,2,3,4,null}
/ \
1,{1,2,3,4,5} 2,{1,2,3,4,6}
再次,如果您插入41234,{1,2,345,87,65},它将如下所示:
4,{1,2,null,null,null}
|
1,{1,2,null,null,null}
/ \
1,{1,2,3,4,null} 2,{1,2,345,87,65}
| |
1,{1,2,3,4,null} 3,{1,2,345,87,65}
/ \ |
1,{1,2,3,4,5} 2,{1,2,3,4,6} 4,{1,2,345,87,65}
执行此操作时,仅存储已插入项目的公共前缀的部分属性,您无需创建所有组合。另外,使用检索值的相同算法来检索部分属性。