Java guava表与多哈希映射的效率比较
我遇到了一些代码,它们是这样做的:Java guava表与多哈希映射的效率比较,java,guava,performance,Java,Guava,Performance,我遇到了一些代码,它们是这样做的: Map<String,String> fullNameById = buildMap1(dataSource1); Map<String,String> nameById = buildMap2(dataSource2); Map<String,String> nameByFullName = new HashMap<String,String>(); Map<String,String> idByN
Map<String,String> fullNameById = buildMap1(dataSource1);
Map<String,String> nameById = buildMap2(dataSource2);
Map<String,String> nameByFullName = new HashMap<String,String>();
Map<String,String> idByName = new HashMap<String,String>();
Set<String> ids = fullNameById.keySet();
for (String nextId : ids) {
String name = nameById.get(nextId);
String fullName = fullNameById.get(nextId);
nameByFullName.put(fullName, name);
idByName.put(name, nextId);
}
在addRelationships2中,我的查询为id
和name
生成值
relations.put(relations.remove(id,"hasFullName"), "hasName", name);
relations.put(name, "hasId", id);
所以我的问题是:
relations=null
之后,表对象将不会被GC'd,我只想告诉大家,在接下来相当长的代码部分中不再使用它表格并不为人所知。另一方面,最高层现在非常清楚地说,“从两个来源收集数据,并从中制作这两个地图。”我还喜欢这样一个事实,即它不会让您怀疑其他两个地图是否正在使用(或不在使用)
注意:我的变量和方法名称已在此处进行了清理,以避免业务领域分散讨论的注意力,我绝对不会将它们命名为AddRelations1或datasource1!同样,最终的代码当然将使用常量而不是原始字符串;博士,但我恐怕你需要离原来的设计更大一步。模拟DB表可能是一个很好的练习,但对我来说,您的代码不是很可读
class IdNameAndFullName {
String id, name, fullName;
}
class IdNameAndFullNameMaps {
Map<String, IdNameAndFullName> byId;
Map<String, IdNameAndFullName> byName;
Map<String, IdNameAndFullName> byFullName;
}
类IDName和FullName{
字符串id、名称、全名;
}
类IdNameAndFullNameMaps{
映射byId;
地图名称;
全名地图;
}
显然,您可以用表
替换类idnamemaps和fullnamemaps
。然而,除了使用一个很好的预先存在的数据结构之外,我看不出其中有什么优点。缺点是:
- 效率损失
- 可读性丧失(出于同样的原因,我不会在这里使用
表
)
- 使用字符串键(您的“hasId”和“hasName”)
Case Maps (ms) Table (ms) Table vs Maps
100000 runs of size 10 2931 3035 104%
10000 runs of size 100 2989 3033 101%
1000 runs of size 1000 3129 3160 101%
100 runs of size 10000 4126 4429 107%
10 runs of size 100000 5081 5866 115%
1 run of size 1000000 5489 5160 94%
所以,对于小数据集,使用表似乎稍微慢一点。10万左右发生了一些有趣的事情,然后到了100万,桌子实际上更快了。我的数据将挂起在100到1000范围内,因此至少在执行时间内,性能应该几乎相同
至于可读性,我的观点是,如果有人试图弄清楚附近发生了什么,并阅读代码,那么就更容易看到意图。如果他们必须实际调试这段代码,可能会有点困难,因为Table
不太常见,需要一些复杂的知识才能理解
我不确定的另一件事是,创建哈希映射是否更有效,或者在映射的所有键随后将被迭代的情况下直接查询表是否更有效。但这是另一个问题:)
喜剧性的结局是,事实上,当我进一步分析代码(数百行)时,我发现nameByFullname.get()在日志记录之外的唯一重要用途(值有问题)是将结果传递给idByName.get()。因此,在最后,我实际上将构建一个idByFullName映射和一个idByName映射,而不需要任何连接,并且不管怎样,都会删除整个表。但我想这是一个很有趣的问题。我用
表
替换了大量的HashMaps
,就像你的一样,并且对结果非常满意。回想一下,HashBasedTable
并不是您可以使用的唯一类型。使用两行表
而不是维护两个映射并直接使用它们,效率要低得多,但只能通过一个常量来实现。@Wasserman比较点是a)生成两个映射并对其进行迭代以生成另外两个映射,vs B)构建1个表,然后从表中获取2个地图。两种情况下的最终输出都是相同的两个映射:nameByFullName
和idByName
。我曾经考虑过这样做,(实际上这是我的第一个想法),但我不喜欢那些毫无意义的数据包类。我不知道你为什么说你的方法更有效。迭代映射键以构建外部数据表示,其中包含所有
class IdNameAndFullName {
String id, name, fullName;
}
class IdNameAndFullNameMaps {
Map<String, IdNameAndFullName> byId;
Map<String, IdNameAndFullName> byName;
Map<String, IdNameAndFullName> byFullName;
}
Case Maps (ms) Table (ms) Table vs Maps
100000 runs of size 10 2931 3035 104%
10000 runs of size 100 2989 3033 101%
1000 runs of size 1000 3129 3160 101%
100 runs of size 10000 4126 4429 107%
10 runs of size 100000 5081 5866 115%
1 run of size 1000000 5489 5160 94%