【问题标题】:Attribute fields vs. attribute-value map属性字段与属性值映射
【发布时间】:2012-03-08 16:52:27
【问题描述】:

我有一个包含大约 10 个属性的 (java) 类,其中许多可能保持未初始化并且在对象的生命周期内未访问

因此,我正在考虑使用 Map<String,Object> 作为属性名称 -> 属性值映射而不是大量字段,以节省资源。
现在我想知道,是否存在任何官方或非官方规则,何时以及如何决定所描述的可能性之一。在我应该考虑使用这样的地图之前,一个类应该有多少属性?我应该使用它吗?

提前感谢您对此的建议/意见。

【问题讨论】:

  • JVM 正在执行比您想象的更智能的优化。所以不,你不需要它。
  • 所以你的意思是,如果我的想法是节省资源,那么JVM可能也会优化它?是的,这听起来很合理,谢谢! :-)
  • @Murat 你所说的实现起来似乎相当复杂,并且至少涉及一个额外的间接和一些开销。另外我不知道有任何 JVM(甚至是学术的)已经实现了这个。所以请发布一些链接.. 现在显然 Java 中未初始化的变量可以占用的最糟糕的东西是 8 字节,所以我们最多保存 80 bytes - overhead of a map 这意味着从内存 pov 解决方案可能更糟,但仍然..

标签: java optimization coding-style


【解决方案1】:

好吧,我假设您这样做是为了节省内存,因为显然您并没有通过访问地图而不是字段来节省 CPU 资源。那么让我们看看效果如何:(假设 64 位 JVM 没有压缩 oops - 这是不现实的,但不应该过多地改变结果,您可以自己轻松计算)

基本上java中的一个字段永远不会占用超过8个字节(引用的字长)。所以这意味着对于你的类有 10 个字段,假设所有字段都未使用,我们可以节省的最好是 8*10 字节 = 80 字节。

现在您想用一个 HashMap 替换它 - 这意味着我们已经为此使用了 8 个额外的字节。此外,HashMap 始终被初始化,因此我们得到以下开销:2 个字头 + 引用 + 3 个整数 + 浮点 + 1 个数组(2 个字开销,4 字节大小,默认情况下 16 个引用)占用 182 bytes 的内存。

恭喜你节省了一大笔-110 bytes

PS:我认为哈希集的后备数组的最小可能默认值是 2,所以你可以使用它并得出均匀的结果。但是,一旦您将对象存储在集合中,您就会从类使用的 Wrapper 对象中获得额外的开销。所以真的是个坏主意。

【讨论】:

  • 看到数学论证很有趣,谢谢!
【解决方案2】:

这与您拥有多少不同的属性无关,而与如何使用它们以及需要什么有关。 Map 将允许更灵活地不具有属性或为不同的实例具有不同的属性或稍后添加属性(通过向Map 添加内容)。但是,如果属性是不同类型的String, Integer, Doubles 等,这将需要创建Object 类型的Map 并在使用它们时强制转换所有值(为你做更多的工作)。

【讨论】:

  • 因此,对于转换问题,我会编写 getter 方法来完成这项工作(当然,所有属性都必须在编译前知道才能工作)。无论如何,我明白你的意思:只有当你需要你的属性像你描述的那样“灵活”时,一个属性值映射才有意义。我在场景中似乎没有意义,我想使用它。感谢您的回答!
【解决方案3】:

我认为地图不是一个好主意。

  • 从 OO 的角度来看,字段是类型及其子类型的属性。想想继承和多态,如何让Map实现OO的那些特性?

  • 即使谈论代码风格,这也不能使您的代码更干净。你如何处理类型转换?异常处理?这些代码不仅仅是字段声明和 getter/setter(如果你有的话)

【讨论】:

  • 这些字段都是private,所以我认为继承不会有问题,但我同意地图构造似乎不是“自然的”。是的,与使用简单的字段 getter/setter 相比,getter 和 setter 代码更难看。
【解决方案4】:

我喜欢 Map 的想法,因为它是真正可选且“非必需”的属性。否则,您将需要一大堆子类和/或您总是需要在 getter 中检查 null。

关于类型,我经常编写代码,将默认值作为第二个参数传递,并使用它来确定返回类型。例如

  int getValue(String key, int defaultValue);
  double getValue(String key, double defaultValue);
  String getValue(String key, String defaultValue);

调用者,而不是 Map,必须知道类型。 YMMV不管你喜欢这种风格...

但是,对于“必要”的属性,我更喜欢真实的字段。

【讨论】:

    猜你喜欢
    • 2018-09-15
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 2017-09-25
    • 1970-01-01
    • 2018-11-04
    相关资源
    最近更新 更多