【问题标题】:Java store boolean array in file and read fastJava将布尔数组存储在文件中并快速读取
【发布时间】:2015-07-22 08:27:29
【问题描述】:

我需要在文件中存储包含 80,000 个项目的布尔数组。我不在乎节省多少时间,我只对数组的加载时间感兴趣。 我没有尝试通过 DataOutputStream 存储它,因为它需要访问每个值。

我尝试通过 3 种方法做到这一点,例如:

  1. 序列化布尔数组
  2. 使用 BitSet 代替布尔数组对其进行序列化
  3. 将布尔数组转换为字节数组,其中 1 为真,0 为假,并由 FileChannel 使用 ByteBuffer 写入

为了测试通过这些方法读取文件的情况,我循环运行了每种方法 1000 次。所以我得到的结果如下所示:

  1. 布尔数组的反序列化需要 574 毫秒
  2. BitSet 的反序列化 - 379 毫秒
  3. 通过 MappedByteBuffer 从 FileChannel 获取字节数组 - 170 毫秒

第一种和第二种方法太长了,第三种可能根本不是方法。

也许有一个最好的方法来完成它,所以我需要你的建议

编辑

每个方法运行一次

  1. 13.8
  2. 8.71
  3. 6.46 适当地 ms

【问题讨论】:

  • 你如何衡量这些数据的执行结果?
  • 在一个循环中加载同一个文件 1000 次不会让您真正了解每次迭代需要多长时间 - 第一次会慢得多,然后文件系统缓存将启动。
  • @Luiggi 我已经在循环中运行了它们每个 1000 次,并通过 System.currentTimeMills() 或 System.nanoTime() 花费时间
  • @Jon 好的,给我一分钟时间测试一下
  • 1. 13.8 2. 8.71 3. 6.46 毫秒

标签: java arrays io boolean


【解决方案1】:

为每个布尔值写入一个字节并开发自定义解析器怎么样?这可能是最快的方法之一。 如果你想节省空间,你也可以将 8 个布尔值放入一个字节,但这需要一些位移操作。

这是一个简短的示例代码:

public void save() throws IOException
{
    boolean[] testData = new boolean[80000];
    for(int X=0;X < testData.length; X++)
    {
        testData[X] = Math.random() > 0.5;
    }
    FileOutputStream stream = new FileOutputStream(new File("test.bin"));

    for (boolean item : testData)
    {
        stream.write(item ? 1 : 0);
    }
    stream.close();
}

public boolean[] load() throws IOException
{
    long start = System.nanoTime();
    File file = new File("test.bin");
    FileInputStream inputStream = new FileInputStream(file);
    int fileLength = (int) file.length();

    byte[] data = new byte[fileLength];
    boolean[] output = new boolean[fileLength];

    inputStream.read(data);
    for (int X = 0; X < data.length; X++)
    {
        if (data[X] != 0)
        {
            output[X] = true;
            continue;
        }
        output[X] = false;
    }
    long end = System.nanoTime() - start;
    Console.log("Time: " + end);
    return output;
}

加载 80.000 个布尔值大约需要 2 毫秒。 使用 JDK 1.8.0_45 测试

【讨论】:

  • 在我的机器上需要 4 到 6 毫秒,有趣,但我使用的是 JDK 1.7.0_79
  • 字节数组的读取耗时 0.71 毫秒,这太神奇了,我无法理解为什么 nio 读取 80.000 字节 6 毫秒,而 FileInputStream 只有一半毫秒?
【解决方案2】:

所以我有一个非常相似的用例,我想序列化/反序列化一个非常大的布尔数组。

我实现了这样的东西, 首先,我将布尔数组转换为整数数组,只是为了组合多个布尔值(这使存储更高效,并且位填充没有问题)
这现在意味着我们必须构建将给出 true/false 的包装器方法

    private boolean get (int index) {
        int holderIndex = (int) Math.floor(index/buckets);
        int internalIndex = index % buckets;
        return 0 != (container[holderIndex] & (1 << internalIndex));
    }

    private void set (int index) {
        int holderIndex = (int) Math.floor(index/buckets);
        int internalIndex = index % buckets;
        int value = container[holderIndex];
        int newValue = value | (1 << internalIndex);
        container[holderIndex] = newValue;
    }

现在要序列化和反序列化,您可以直接将其转换为字节流并写入文件。

我的源代码,用于reference

【讨论】:

    猜你喜欢
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多