我目前正在ColdFusion 9中实现类似于数据透视的数据可视化的通用模型。
我对支持多个度量并不感兴趣,并且该模型公开了一个numeric valueAt(string colKey, string rowKey)
函数,该函数可以被视图调用,以便根据列和行维度检索度量的结果聚合。
例如,对于下面的数据集,如果度量为AVG(Age)
且列维度为Rank
,那么model.valueOf('3', '')
将返回2.33
。
Wine Age Rank
WineA 3 3
WineB 4 2
WineC 2 3
WineD 2 3
现在,我自然想到的数据结构是使用java.util.HashMap
来存储计算数据,使用转换为字符串作为键的列和行值的组合。这意味着根据数据集的不同,我可能会有很多以相同前缀开头的密钥。
我故意创建了一个包含多个具有相同前缀的字符串的大型数据集(100万个条目),并使用默认的java String.hashCode()
算法和MurmurHash3检查了我将获得的桶冲突的百分比。 / p>
以下是我构建数据集样本的方法:
<cfset maxItemsCount = 1000000>
<cfset tokens = ['test', 'one', 'two', 'tree', 'four', 'five']>
<cfset tokensLen = arrayLen(tokens)>
<cfset items = []>
<cfset loopCount = 1>
<cfloop condition="arrayLen(items) lt maxItemsCount">
<cfset item = ''>
<cfloop from="1" to="#tokensLen#" index="i">
<cfset item = listAppend(item, tokens[i] & loopCount, '_')>
<cfset arrayAppend(items, item)>
</cfloop>
<cfset ++loopCount>
</cfloop>
将数组初始化为 2 * entries count
,我与 String.hashCode()
和发生 27%冲突22% Murmur 。 java.util.HashMap
只花了2580毫秒来存储和检索密钥一次。
我正在寻找有关如何提高性能的想法,无论是使用不同的数据结构(可能是嵌套的哈希映射?)还是找到一种方法来减少冲突次数而不会影响API签名
谢谢!
答案 0 :(得分:1)
有一百万个条目,总会有一些冲突(除非你的数组比1e12条目长得多:D)。我猜MurmurHash在这里做得很完美,但你可以尝试用MD5进行比较(这有点保证完美的工作)。
现在,我脑海中浮现的数据结构是使用java.util.HashMap来存储计算数据,使用转换为字符串作为键的列和行值的组合。这意味着根据数据集的不同,我可能会有很多以相同前缀开头的密钥。
你正在连接字符串,因此产生了相当多的垃圾。创建
可能更好@Value static class Key {
private final String row;
private final String column;
}
作为HashMap
的密钥,其中@Value
是Lombok注释,生成所有无聊的内容,例如equals
,hashCode
和构造函数。< / p>
你可以轻松地在没有龙目岛的情况下轻松实现,甚至更好:
static class Key {
Key(String row, String column) {
// Do NOT use 31 as a multiplier as it increases the number of collisions!
// Try Murmur, too.
hashCode = row.hashCode() + 113 * column.hashCode();
this.row = row;
this.column = column;
}
public int hashCode() {
return hashCode;
}
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Key)) return false;
Key that = (Key) o;
// Check hashCode first.
if (this.hashCode != that.hashCode) return false;
if (!this.row.equals(that.row)) return false;
if (!this.column.equals(that.column)) return false;
return true;
}
private final int hashCode;
private final String row;
private final String column;
}