6.10 如何进行整型读写

我们在前面的小节里面也谈到了对整型的读取,接下来我们通过FileAdapter来介绍对本地整型数据的操作,以及整型列表对象的使用,并与java.util.ArrayList的性能进行对比。

与读取字节类似,在构建一个FileAdapter对象后,可以通过getIntWriter方法获取IntWriteAdapter对象进行整数写操作:

  1. FileAdapter fa = new FileAdapter(path);
  2. IntWriteAdapter wa = fa.getIntWriter();

或者指定开始位置,向后写入intNum个整数:

  1. IntWriteAdapter wa = getIntWriter(long beginIndex, long intNum)

如果不指定起始位置,默认是追加到最后。注意,在使用时容易出现不追加到最后,而反复覆盖已有位置的情况,比如:

  1. IntWriteAdapter wa = fa.getIntWriter();
  2. int[] nums = new int[5];
  3. wa.writeInt(nums);
  4. wa.writeInt(nums);
  5. wa.writeInt(nums);

上面代码的结果是nums没有追加到文件最后,而是反复覆盖相同位置,如果修改为:

  1. IntWriteAdapter wa = fa.getIntWriter();
  2. int[] nums = new int[5];
  3. wa.writeInt(nums);
  4. wa = fa.getIntWriter();
  5. wa.writeInt(nums);
  6. wa = fa.getIntWriter();
  7. wa.writeInt(nums);

结果就每次追加到文件最后了,这是因为每次调用fa.getIntWriter(),它会自动调整文件大小,计算文件的最后位置,如果沿用旧的IntWriteAdapter,则没有获取到文件更新后的最后位置,导致反复覆盖相同位置。

同样,构建一个FileAdapter对象后,可以通过getIntReader方法获取IntReadAdapter对象进行整数读操作:

  1. FileAdapter fa = new FileAdapter(path);
  2. IntReadAdapter ra = fa.getIntReader();

或者指定开始位置读取intNum个整数:

  1. IntReadAdapter ra = fa.getIntReader(long beginIndex, long intNum);

跟上面谈到的FTTP使用类似,操作结束时,需要进行关闭:

  1. fa.close();

除了提供对整型数据的便利操作外,框架还提供了ListInt数组用于对整型数据的存放,ListInt在容量和排序的性能上都比java.util.ArrayList要高,接下来我们以一个综合的demo:ListIntTest来演示对整型数据的读写、装载、排序,分别在运行时输入参数0、1、2进行区分。

下面介绍运行步骤。

1)读写演示,代码如下:

  1. java -cp fourinone.jar; ListIntTest 0

如果命令参数是0,ListIntTest调用了writeReadTest,首先在同一运行目录下建立一个"data.txt"的数据文件,写入了100个整数(每个整数是随机生成的,取值范围在1千万内),然后再每10个一批地将所有整数读出并输出显示,如图6-6所示。

6.10 如何进行整型读写 - 图1

图6-6 ListIntTest0

2)装载演示,代码如下:

  1. java -cp fourinone.jar; ListIntTest 1

如果命令参数是1,ListIntTest调用了capacityTest,它按先后顺序运行了ListInt和ArrayList的装载容量测试进行对比。

首先通过ArrayAdapter获取到一个ListInt实例:

  1. ListInt ai = ArrayAdapter.getListInt();

然后往里面写入2千万个整数(取值范围为1千万内)。接着,再建立一个ArrayList的实例,同样往里面写入2千万个整数,为了能看清楚过程,每写入1千万后会输出一条信息。运行结果如图6-7所示。

6.10 如何进行整型读写 - 图2

图6-7 ListIntTest1

我们发现,向ListInt写入2千万个整数是可以顺利完成的,但是向ArrayList写入2千万个整数则导致内存溢出,查看内容输出可以看到,向ArrayList写入1千万个整数是正常完成的,但是再大就出现问题了(这里用的是一台普通的内存为4GB的PC,JVM的内存使用会小于4GB)。

3)排序演示,代码如下:

  1. java -cp fourinone.jar; ListIntTest 2

如果命令参数是2,ListIntTest调用了sortTest,比方法可以输入一个参数,用来表示要测试排序多少个整数,这里测试了5百万个数字排序。首先程序建立了一个"data.txt"文件并生成了5百万个无序整数(取值范围为1千万以内),然后先后使用ListInt和ArrayList进行排序。

对于ListInt排序,我们可以看到先从文件中读出所有整数到一个数组中,然后使用ListInt的sort方法,输入该数组进行排序,最后再输出前100个数字进行验证。对于ArrayList来说,先通过readListIntAll直接从文件读取所有整数到一个ArrayList中,然后再利用Collections.sort对该ArrayList进行排序,最后同样读取前100个数字进行验证。结果如图6-8所示。

6.10 如何进行整型读写 - 图3

图6-8 ListIntTest2

我们可以看到,在同台(2.4GHz,4G内存)机器上,利用ListInt完成5百万数字排序时间是1秒,而ArrayList则用了7秒。我们大体可以看到ListInt相对于ArrayList,对于整数可以存储更多,排序更快,使用起来更高效。

完整demo源码如下:

  1. // ListIntTest
  2. import com.fourinone.FileAdapter;
  3. import com.fourinone.FileAdapter.IntReadAdapter;
  4. import com.fourinone.FileAdapter.IntWriteAdapter;
  5. import com.fourinone.ArrayAdapter;
  6. import com.fourinone.ArrayAdapter.ListInt;
  7. import java.util.Random;
  8. import java.util.ArrayList;
  9. import java.util.Collections;
  10.  
  11. public class ListIntTest
  12. {
  13. public void intWrite(String path, int num)
  14. {
  15. System.out.println("write "+num+" number to "+path+"...");
  16. FileAdapter fa = new FileAdapter(path);
  17. fa.delete();
  18. IntWriteAdapter wa = fa.getIntWriter();
  19. Random rad = new Random();
  20. int[] nums = new int[num];
  21. for(int i=0;i<nums.length;i++){
  22. int thenum = rad.nextInt(10000000);
  23. nums[i]=thenum;
  24. }
  25. wa.writeInt(nums);
  26. System.out.println("write done.");
  27. fa.close();
  28. }
  29.  
  30. public void intRead(String path)
  31. {
  32. System.out.println("read number from "+path+"...");
  33. FileAdapter fa = new FileAdapter(path);
  34. IntReadAdapter ra = null;
  35. int total=0;
  36. for(int n=0;n<10;n++){
  37. ra = fa.getIntReader(n*10,10);
  38. int[] its = ra.readIntAll();
  39. for(int i:its){
  40. System.out.println(i);
  41. total++;
  42. }
  43. }
  44. System.out.println("total:"+total);
  45. fa.close();
  46. }
  47.  
  48. public void listintCapacity()
  49. {
  50. System.out.println("insert int into ListInt...");
  51. ListInt ai = ArrayAdapter.getListInt();
  52. Random rad = new Random();
  53. for(int i=0;i<20000000;i++)
  54. ai.add(rad.nextInt(10000000));
  55.  
  56. System.out.println(ai.size()+" number be inserted.");
  57. }
  58.  
  59. public void arraylistCapacity()
  60. {
  61. System.out.println("insert int into ArrayList...");
  62. ArrayList<Integer> al = new ArrayList<Integer>();
  63. Random rad = new Random();
  64. int i=0;
  65. while(i<20000001){
  66. al.add(rad.nextInt(10000000));
  67. if(i%10000000==0){
  68. System.out.println(i+" number be inserted.");
  69. }
  70. i++;
  71. }
  72. }
  73.  
  74. public void listintSort()
  75. {
  76. FileAdapter fa = new FileAdapter("data.txt");
  77. int[] rls = fa.getIntReader().readIntAll();
  78. ListInt is = ArrayAdapter.getListInt();
  79.  
  80. System.out.println("ListInt sort begin...");
  81. long begin = (new java.util.Date()).getTime();
  82. is.sort(rls);
  83. long end = (new java.util.Date()).getTime();
  84. System.out.println("sort done time:"+(end-begin)/1000+"s");
  85.  
  86. System.out.print("check top 100 data:");
  87. for(int i=0;i<100;i++)
  88. {
  89. System.out.print(rls[i]+" ");
  90. }
  91. System.out.println("...");
  92. }
  93.  
  94. public void arraylistSort()
  95. {
  96. FileAdapter fa = new FileAdapter("data.txt");
  97. ArrayList<Integer> rls = (ArrayList)fa.getIntReader().readListIntAll();
  98.  
  99. System.out.println("ArrayList sort begin...");
  100. long begin = (new java.util.Date()).getTime();
  101. Collections.sort(rls);
  102. long end = (new java.util.Date()).getTime();
  103. System.out.println("sort done time:"+(end-begin)/1000+"s");
  104.  
  105. System.out.print("check top 100 data:");
  106. for(int i=0;i<100;i++)
  107. {
  108. System.out.print(rls.get(i)+" ");
  109. }
  110. System.out.println("...");
  111. }
  112.  
  113. public static void writeReadTest()
  114. {
  115. ListIntTest test = new ListIntTest();
  116. test.intWrite("data.txt",100);
  117. test.intRead("data.txt");
  118. }
  119.  
  120. public static void capacityTest()
  121. {
  122. ListIntTest test = new ListIntTest();
  123. test.listintCapacity();
  124. test.arraylistCapacity();
  125. }
  126.  
  127. public static void sortTest(int num)
  128. {
  129. ListIntTest test = new ListIntTest();
  130. test.intWrite("data.txt",num);
  131. test.listintSort();
  132. test.arraylistSort();
  133. }
  134.  
  135. public static void main(String[] args)
  136. {
  137. if(args[0].equals("0"))
  138. {
  139. writeReadTest();
  140. }
  141. else if(args[0].equals("1"))
  142. {
  143. capacityTest();
  144. }
  145. else if(args[0].equals("2"))
  146. {
  147. sortTest(5000000);
  148. }
  149. }
  150. }