【发布时间】:2016-12-01 03:32:53
【问题描述】:
给定一个列表,其中每个条目都是一个看起来像的对象
class Entry {
public String id;
public Object value;
}
多个条目可以具有相同的id。我需要一个可以访问属于某个 id 的所有值的地图:
Map<String, List<Object>> map;
我实现这个的算法:
for (Entry entry : listOfEntries) {
List<Object> listOfValues;
if (map.contains(entry.id)) {
listOfValues = map.get(entry.id);
} else {
listOfValues = new List<Object>();
map.put(entry.id, listOfValues);
}
listOfValues.add(entry.value);
}
简单地说:我转换了一个看起来像这样的列表
ID | VALUE
---+------------
a | foo
a | bar
b | foobar
到一张看起来像的地图
a--+- foo
'- bar
b---- foobar
如您所见,contains 为源列表的每个条目调用。这就是为什么我想知道是否可以改进我的算法,如果我预先对源列表进行排序然后这样做:
List<Object> listOfValues = new List<Object>();
String prevId = null;
for (Entry entry : listOfEntries) {
if (prevId != null && prevId != entry.id) {
map.put(prevId, listOfValues);
listOfValues = new List<Object>();
}
listOfValues.add(entry.value);
prevId = entry.id;
}
if (prevId != null) map.put(prevId, listOfValues);
第二种解决方案的优点是我不需要为每个条目调用map.contains(),但缺点是我必须先进行排序。此外,第一种算法更容易实现且不易出错,因为您必须在实际循环之后添加一些代码。
因此我的问题是:哪种方法性能更好?
示例是用 Java 伪代码编写的,但实际问题也适用于其他编程语言。
【问题讨论】:
-
没有实际回答您的问题,您的数据结构称为多图。您可以在 Guava 的
TreeMultimap和/或MultimapBuilder的帮助下获得所需的内容。 -
@Sorin 的回答在很大程度上是正确的。在性能方面,我自己也遇到过类似的问题。在我的情况下(整数 id;数十亿个条目;许多重复的 id),第二种方法要快得多,因为排序是缓存高效的并且与一个很小的常数相关联。但是,在您的情况下,对字符串进行排序会抵消排序的缓存效率; large
Object也可能会稍微降低排序性能。此外,如果您没有很多重复的 id,则第一种方法可能会更快。不过,我不能肯定地说。
标签: java algorithm performance sorting dictionary