7

这是一个愚蠢的问题,但它就在这里。

我有一个多线程程序和一个独特元素的“全局”集合。由于性能,我拒绝了 ConcurrentHashMap 的同步 Set 实现。我真的不需要 Map 的 Value 部分,所以我想在内存使用方面使用 java 中最小的 Object。我以不同的方式解决了这个问题(在 Map 中多次引用单个布尔对象),但我仍然很好奇 Java 中最小的对象是什么。我一直认为它是布尔值,但我认为这不是真的(Java-布尔原始类型-大小原始数据类型

4

5 回答 5

5

实际上,这并不重要,因为每个关联的值部分都固定为参考。您甚至可以null在这里使用 as value,但任何其他(固定)对象引用都应该没问题(有时更方便)。我更喜欢Boolean.TRUE(或类似的“众所周知的”单身人士)。然后,您可以通过以下方式测试会员资格

if (myMap.get(someKey) != null) { ... }

此外

if (myMap.containsKey(someKey)) { ... }
于 2012-08-26T19:05:43.930 回答
5

如果你想要一个Set<K>由 a 支持的 a ConcurrentHashMap,你应该使用Collections.newSetFromMap,例如

final Set<K> set = Collections.newSetFromMap(new ConcurrentHashMap<K, Boolean>());

现在,如果你真的想重新发明轮子,并且非常关心内存使用情况,我建议你只使用一个 plainObject作为你的值。由于 Java 中的每个对象都继承自Object(通用基类),因此内存中任何对象的大小都必须大于或等于 plain 的大小Object。您不能使用原语,因为泛型类型参数必须是Objects。

编辑:实际上,在这里分配一个特定对象用作您的值将比使用可能分配给任何情况的预先存在的对象占用更多的内存。您可以只使用对在 VM 初始化期间或多或少总是分配的对象的引用,例如Object.class. 不过,我真的建议您只使用第一个解决方案。

于 2012-08-26T19:09:22.927 回答
2

对象的大小包括:

  • 它持有的实例变量的大小
  • 一个 8 或 16 字节的标头(取决于 Hotspot VM(32/64 位))
  • 填充:它的大小总是填充为 8 字节的倍数。

例如(假设 32 位 JVM):

public MyBoolObject {
  boolean flag;
}

将占用16 bytes:(8bytes标题)+ 1byte(实例变量)+ 7bytes(填充)。
由于您对地图值不感兴趣,因此可以将它们设置为 null。这会消耗4或占用8堆栈中的内存(32/64 位)。

您还可以查看这个关于众所周知的 Java 数据结构的成本/元素的好列表: http ://code.google.com/p/memory-measurer/wiki/ElementCostInDataStructures

于 2012-08-26T20:40:44.520 回答
0

原始数据类型不是对象。

由于java中的所有对象都必须继承自超类Object。那么Java中最小的可以想象的对象将是您定义的没有成员的类。这样的课程将毫无用处。

于 2012-08-26T19:05:36.027 回答
0

该类Object是可实例化的,它的实例绝对是 Java 中最小的对象。但是,许多其他对象具有完全相同的占用空间,Integer并且Boolean是 64 位 VM 上的示例。这是由于堆内存对齐。

于 2012-08-26T19:10:41.127 回答