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);
所以我的问题是:

  • 我通过处理器、内存或GC负载所做的工作是否存在潜在的低效?我不这么认为,但我对桌子的效率不太熟悉。我知道在
    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”)

    因此,我自己做了一些小型基准测试,得出结论:就执行时间而言,这两种方法几乎没有差异。通过对数据集大小的交易,我使正在处理的数据的总大小保持不变。我做了4次运行,并从所有4次运行中为每个实现选择了最短的时间。令人欣慰的是,这两种实现在同一次运行中总是最快的。我的代码可以找到。以下是我的结果:

    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%