我很快写了这个片段来完成这项工作
private void map() {
for (KVPair kvPair : content) {
String k = kvPair.getKey();
String v = kvPair.getValue();
if (mappedContent.containsKey(k)) {
List<String> values = mappedContent.get(k);
values.add(v);
} else {
List<String> values = new ArrayList<>();
values.add(v);
mappedContent.put(k, values);
}
}
}
它有效,当使用1k,2k,4k和8k随机数据运行时,我获得以下性能(平均100,000次运行)
Running with 1,000 pairs
[perfRun] 100000 iterations took 3 seconds
[perfRun] Run time: 3758786000 ns. 1 iteration takes 37 us
Running with 2,000 pairs
[perfRun] 100000 iterations took 6 seconds
[perfRun] Run time: 6675544000 ns. 1 iteration takes 66 us
Running with 4,000 pairs
[perfRun] 100000 iterations took 13 seconds
[perfRun] Run time: 13337145000 ns. 1 iteration takes 133 us
Running with 8,000 pairs
[perfRun] 100000 iterations took 27 seconds
[perfRun] Run time: 27109480000 ns. 1 iteration takes 271 us
粗略地说,当尺寸增加一倍时,时间会增加一倍。我会采取线性增长,但我们还是想知道,我们能做得更好吗?是否可以使用恒定时间映射事物?
答案 0 :(得分:3)
我可以看到,mappedContent.containsKey(k)
大概需要BigO(n)
,你可以通过null
检查,
for (KVPair kvPair : content) {
String k = kvPair.getKey();
String v = kvPair.getValue();
List<String> values = mappedContent.get(k);
if (values!=null) {
values.add(v);
} else {
values = new ArrayList<>();
values.add(v);
mappedContent.put(k, values);
}
}
答案 1 :(得分:1)
根据@ Quoi的回答,不确切知道在空检查后保存else块是否有所作为
for (KVPair kvPair : content) {
String k = kvPair.getKey();
List<String> values = mappedContent.get(k);
if (values == null) {
values = new ArrayList<>();
mappedContent.put(k, values);
}
values.add(kvPair.getValue());
}
您也可以对列表的大小做出一些假设,因此您将该大小传递给列表构造函数并节省列表重新调整大小所需的时间。如果内存不是问题,您可以将content.size() + 1
作为列表的大小。
答案 2 :(得分:0)
除非你能改变基础数据结构,否则你不能比线性时间更好。
请考虑这一点:您有一个包含 n 唯一条目的列表。映射必须访问的每个人。假设访问成本1.然后必须 n 访问。因此,您的基准测试指出, n * 1 = n 的复杂度或线性时间。
现在,如果你能拥有一个可以共享数据但同时提供两个接口的数据结构,那么你可以在两者之间切换时获得恒定的时间。显然,你的静态类型不同于你的例子。