【问题标题】:Compressing array of integers in java在java中压缩整数数组
【发布时间】:2009-07-05 00:40:21
【问题描述】:

我有一些非常大的整数数组要压缩。
然而,在 java 中做到这一点的方法是使用这样的东西 -

int[] myIntArray;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new DeflaterOutputStream(byteArrayOutputStream));
objectOutputStream.writeObject(myIntArray);

注意int数组首先需要通过java转换为字节。 现在我知道这很快,但它仍然需要创建一个全新的字节数组并扫描整个原始 int 数组,将其转换为字节并将值复制到新的字节数组。

有什么方法可以跳过字节转换并立即压缩整数?

【问题讨论】:

  • 这没有意义。压缩算法需要字节,而不是整数。
  • 您的 int 数组在哪里转换为字节? ObjectOutputStream 获取您的对象并直接对其进行序列化。 DeflaterOutputStream 对序列化的结果进行压缩,然后将压缩后的结果存储在一个 ByteArrayOutputStream 中。我认为这正是你想要发生的事情......
  • 在我的情况下,我要压缩的对象是一个 int[] 数组。序列化过程将其转换为字节,这是我要跳过的步骤。
  • 为什么?你说你想跳过一个你不需要知道的步骤。每个阶段都有一个数据副本,解压缩时也是如此。如果性能是您的问题,您希望节省多少时间?您是否意识到,即使是少量数据,创建对象的成本也要高得多。

标签: java compression


【解决方案1】:

跳过ObjectOutputStream,直接将ints 存储为四个bytes。例如,DataOutputStream.writeInt 是一种简单的方法。

【讨论】:

    【解决方案2】:

    嗯。除非有很多冗余,否则通用压缩算法不一定能很好地压缩二进制值数组。根据您对数据的了解,您可能会更好地开发自己的东西。

    您实际上要压缩的是什么?

    【讨论】:

      【解决方案3】:

      您可以使用Protocol Buffers 使用的representation。每个整数由 1-5 个字节表示,具体取决于其大小。

      此外,新的“打包”表示意味着您基本上可以获得一些“标题”来说明它有多大(以及它在哪个字段中),然后是数据。 ObjectOutputStream 可能也是这样做的,但这是 PB 的最新创新:)

      请注意,这将基于大小进行压缩,而不是基于整数出现的频率。这将极大地影响它是否对您有用。

      【讨论】:

        【解决方案4】:

        一个字节数组不会为你节省太多内存,除非你把它变成一个包含无符号整数的字节数组,这在 Java 中是非常危险的。它将用额外的处理时间来代替内存开销,用于代码的步骤检查。这对于数据存储来说可能是正确的,但是已经有数据存储解决方案了。
        除非您出于序列化目的这样做,否则我认为您是在浪费时间。

        【讨论】:

          【解决方案5】:

          在您的示例中,您正在将压缩流写入 ByteArrayOutputStream。您的压缩数组需要存在于某个地方,如果目标是内存,那么 ByteArrayOutputStream 是您可能的选择。您还可以将流写入套接字或文件。在这种情况下,您不会在内存中复制流。如果您的阵列是 800MB 并且您在 1GB 中运行,您可以使用包含的示例轻松地将阵列写入压缩文件。更改将用文件流替换 ByteArrayOutputStream。

          ObjectOutputStream 格式实际上相当有效。它不会在内存中复制您的数组,并且具有用于有效写入数组的特殊代码。

          想要使用内存中的压缩数组吗?您的数据是否适合稀疏数组?当您的数据有很大差距时,稀疏数组很好。

          【讨论】:

            【解决方案6】:

            如果保证整数数组没有重复,则可以使用 java.util.BitSet。

            由于它的基本实现是一个位数组,每个位指示某个整数是否存在于 BitSet 中,它的内存使用率非常低,因此需要更少的空间来序列化。

            【讨论】:

            • 但 bitset 仅在值为 0 或 1 时才有帮助,而我的值范围为 integer.maxvalue,当然没有重复
            • 不,java.util.BitSet 可以存储任意数量的唯一整数。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-08-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多