Java序列化的效率如何?

时间:2016-06-25 00:00:51

标签: java serialization

我们有一个名为Row的类,它表示结果集中的一行。我们需要在文件中写一个List<Row>,以便以后可以检索它。

实现此目的的一种方法是使用Java的序列化支持。

我想最好的方法是在Row类中实现序列化。然后我们将使用serialize的{​​{1}}方法,以便写入文件。

我想知道,这会有多高效?与仅编写将我们的List<Row>对象转换为CSV文件的CSV文件适配器相比,它会占用更多空间吗?

2 个答案:

答案 0 :(得分:4)

  

与仅编写将List对象转换为CSV文件的CSV文件适配器相比,它会占用更多空间吗?

这取决于Row的类型,以及您要保存的数据的大小和其他方面 1

一方面,Java序列化协议包括序列化中提到的每个类的元数据。这需要很大的空间。

另一方面:

  • Java序列化仅包含每个序列化一次的元数据。因此,如果序列化同一类的大量实例,则元数据成本变得无关紧要。
  • 在CSV文件中,所有非文本数据都必须转换为文本。在某些情况下(例如,大数,浮点数,布尔值),文本表示将大于Java序列化中使用的二进制表示。

1 - 例如,随机数的数组与零和1的数组。在第一种情况下,Java序列化会更好,而在第二种情况下,CSV会更好。

但我认为你可能会关注错误的事情:

  • 除非您生成的文件很大,否则大小可能并不重要。磁盘空间很便宜。
  • 在任何一种情况下,文件都可能是可压缩的,较低密度的形式可能更具可压缩性。
  • 更重要的是表述是否适合目的;例如
    • 你想要它是人类可读的吗?
    • 您是否希望非Java程序(包括shell脚本)可以读取它?
    • 您是否需要担心Java代码的更改会引入类与序列化版本问题?
    • 您希望能够传输数据吗? (写作或阅读时。)

答案 1 :(得分:3)

Java序列化的空间效率在某些情况下 ,而不是简单地写入CSV文件,因为它存储额外的元数据以识别类类型。

我用两个简单的测试程序验证了这种情况。第一个将一个int数组写入.csv文件。

import java.io.*;

public class CSVDemo {
  public static void main(String [] args) {
    try {
       PrintWriter pw = new PrintWriter(new File("dummy.csv"));
       StringBuilder sb = new StringBuilder();
       for(int i = 0; i < 1000; i++){
         sb.append(1);
         sb.append(",");
       }

       pw.write(sb.toString());
       pw.close();
       System.out.printf("Data is saved in dummy.csv");
    } catch(FileNotFoundException e) {
        e.printStackTrace();
    }
  }
}

第二个将包含int数组的对象序列化为.ser文件。

import java.io.*;

public class SerializeDemo
{
   public static void main(String [] args)
   {
      DummyData dummy = new DummyData();

      try {
         FileOutputStream fileOut = new FileOutputStream("dummy.ser");
         ObjectOutputStream out = new ObjectOutputStream(fileOut);
         out.writeObject(dummy);
         out.close();
         fileOut.close();
         System.out.printf("Serialized data is saved in dummy.ser");
      } catch(IOException i) {
          i.printStackTrace();
      }
   }

   public static class DummyData implements java.io.Serializable{
     int[] data = new int[1000];
     public DummyData(){
       for(int i = 0; i < 1000; i++){
         data[i] = 1;
       }
     }
   }
}

.ser文件占用了4079个字节。 .csv文件占用了2000个字节。当然,这只是对用例的略微简化(我将int等同于你的Row类型),但总的趋势应该是相同的。

尝试使用更大的数字会产生相同的结果。使用100000英特的结果为.serv约为400KB,而.csv

则为200KB

但是,正如下面的评论指出的那样,如果选择int的随机值,.csv实际上会变大。