使用 SparseIntArray 而不是 HashMap <Integer, Integer> with putSerializable



当我在Android中使用具有Integer键和数据值的HashMap时,我在Eclipse中得到此消息:

Use new SparseIntArray(...) for better performance

现在的问题是SparseIntArray()不实现Serializable接口,不能与onRestoreInstanceState()中的getSerializable()putSerializable()一起使用。

  1. 使用SparseIntArray()代替HashMap<Integer, Integer>有多重要?

  2. 我应该经历使SparseIntArray可序列化的麻烦吗?(我的第一个想法是制作一个实现Serializable的包装器类,这是正确的方法吗?)

1)用SparseIntArray代替HashMap有多重要?

这取决于你如何使用它。但是,除非您尝试像这样表示许多和/或大型"数组",否则差异不太可能显着。

请注意,Java SE没有任何稀疏数组类,这通常不是问题。

2)我应该经历使SparseIntArray可序列化的麻烦吗?(我的第一个想法是制作一个实现Serializable的包装器类,这是正确的方法吗?)

见上面和下面。

实现包装器听起来很合理…如果你非要这么麻烦的话。另一种方法可能是声明SparseIntArray的可序列化子类。建议声明自定义readObjectwriteObject方法。


SparseIntArray类(源代码)使用一对int数组来表示映射中的键和值,并使用二进制搜索来进行查找。键按顺序保存,没有"漏洞",并且使用二进制搜索执行查找。这意味着以下内容:

  • SparseIntArray的内存使用量大约是同等HashMap的10倍。这是由于以下几个因素造成的:

    • 哈希表数组每个条目大约有1个引用(取决于表有多满…),

    • 键和值必须在HashMap中作为Integer对象"装箱",并且

    • HashMap中的每个条目都需要一个"node"对象,该对象在标准实现中具有相当重的权重- 4个字段。

    (但是,如果您以正确的方式创建Integer对象,则可以通过Integer类实例缓存的效果来减轻"装箱"开销。)

    相比之下,稀疏版本需要2 * capacity 4字节字。

  • 查找(即get)是O(logN)O(1)HashMap的比较。

  • 对于HashMap,随机插入是O(N),而O(1)。(这是因为插入必须平均移动现有条目的一半,以便新条目可以添加到数组中的正确位置。)

  • 顺序插入(按键序升序)为O(1)

所以"哪个是最好的"显然取决于你在优化什么,你如何使用数据结构,以及它将变得有多大。

使用HashMap<Integer, Integer>的问题是每个键和值都需要装箱。这种影响的范围从零到由于产生大量垃圾和/或内存使用而给系统带来沉重的负载(更不用说装箱/拆箱值带来的轻微性能损失)。(这些问题也推动了几个第三方原语集合框架的开发。)

如果您认为SparseIntArray的好处值得拥有,那么我认为您使用包装器类的方法是合理的。另一种方法是让它实现Parcelable,它也可以用来保存/恢复实例状态。

最新更新