)
数组 32 位 8 8 16 16 32 32 64 64 32 32
64 位 8 8 16 16 32 32 64 64 64 (32*) 64 (32*)
* 对象字段的大小以及用于各对象元数据条目的数据的大小可通过 压缩引用或压缩 OOP 技术减小到 32 位。 压缩引用和
压缩普通对象指针 (OOP) IBM 和 Oracle
JVM 分别通过压缩引用 (-Xcompressedrefs) 和压缩 OOP (-XX:+UseCompressedOops) 选项提供对象引 用压缩功能。利用这些选项,即可在 32 位(而非 64 位)中存储对象字段和对象元数据值。在应用程序从 32 位 Java 运行时迁移到 64 位 Java 运行时的时候,这能消除 Java 堆内存使用量增加 70% 的负面影响。请注意,这些选 项对于本机堆的内存使用无效,本机堆在 64 位 Java 运行时中的内存使用量仍然比 32 位 Java 运行时中的使用量高 得多。
Java 集合的内存使用 在大多数应用程序中,大量数据都是使用核心 Java API 提供的标准 Java Collections 类来存储和管理的。如果内存占 用对于您的应用程序极为重要,那么就非常有必要了解各集合提供的功能以及相关的内存开销。总体而言,集合功能 的级别越高,内存开销就越高,因此使用提供的功能多于您需要的功能的集合类型会带来不必要的额外内存开销。 其中部分最
常用的集合如下:
HashSet HashMap Hashtable LinkedList ArrayList
除了 HashSet 之外,此
列表是按功能和内存开销进行降序排列的。(HashSet 是包围一个 HashMap 对象的包装器, 它提供的功能比 HashMap 少,同时容量稍微小一些。)
Java 集合:HashSet 是 Set 接口的实现。Java Platform SE 6 API
文档对于 HashSet 的描述如下:
HashSet
一个不包含重复元素的集合。更正式地来说,set(集)不包含元素 e1 和 e2 的配对 e1.equals(e2),而且 至多包含一个空元素。正如其名称所表示的那样,这个接口将建模数学集抽象。 包含的功能比 HashMap 要少,只能包含一个空条目,而且无法包含重复条目。该实现是包围 HashMap 的一 个包装器,以及管理可在 HashMap 对象中存放哪些内容的 HashSet 对象。限制 HashMap 功能的附加功能表示 HashSet 的内存开销略高。 图 6 展示了 32 位 Java 运行时中的一个 HashSet 的布局和内存使用:
HashSet
中的一个 图 6. 32 位 Java 运行时中的一个 HashSet 的内存使用和布局
图 6 展示了一个 java.util.HashSet 对象的 shallow 堆(独立对象的内存使用)以及保留堆(独立对象及其子对象 的内存使用),以字节为单位。shallow 堆的大小是 16 字节,保留堆的大小是 144 字节。创建一个 HashSet 时,其 默认容量(也就是该集中可以容纳的条目数量)将设置为 16 个条目。按照默认容量创建 HashSet,而且未在该集中 输入任何条目时,它将占用 144 个字节。与 HashMap 的内存使用相比,超出了 16 个字节。表 2 显示了 HashSet 的 属性:
表 2. 一个 HashSet 的属性 16 个条目 默认容量 144 个字节 空时的大小 开销 16 字节加 HashMap 开销 集合的开销 一个 10K 集合的开销 16 字节加 HashMap 开销 O(1):所用时间是一个常量时间,
无论要素数量如何都是如此(假设无散列冲突) 搜索/插 删
搜索 插入/删除性能 Java 集合:HashMap
HashMap
是 Map 接口的实现。Java Platform SE 6 API
文档对于 HashMap 的描述如下:
一个将键映射到值的对象。一个映射中不能包含重复的键;每个键仅可映射到至多一个值。
HashMap
提供了一种存储键/值对的方法,使用散列函数将键转换为存储键/值对的集合中的索引。这允许快速访问数 据位置。允许存在空条目和重复条目;因此,HashMap 是 HashSet 的简化版。
HashMap
将实现为一个 HashMap$Entry 对象数组。图 7 展示了 32 位 Java 运行时中的一个 HashMap 的内存使用和布
局:
中的一个 图 7. 32 位 Java 运行时中的一个 HashMap 的内存使用和布局
如 图 7 所示,创建一个 HashMap 时,结果是一个 HashMap 对象以及一个采用 16 个条目的默认容量的 对象数组。这提供了一个 HashMap,在