2019-06-25
关键字:二维数组列表、生成排列整齐的数组
1、需求
有的时候我们可能会遇到需要生成一大串印刷格式严谨的数组的需求。比如下图这种类型的
虽然数据的排列是否具有格式化完全不会影响程序运行的正确性与效率性。但一个清爽的排版往往能给人带来非常良好的阅读体验,很多程序员在书写这种数组时都会留意一下数据的排版情况。
数据量少的时候完全可以纯手工排版,数据量一多时可能就得上程序以让它自动生成了。通过程序自动生成数组时,多数人往往会通过打印时加一个制表符 ' ' 以求能稍微对齐一些。但事实上,' ' 制表符的对齐性其实是非常差的。
那有没有一种办法,可以生成一个绝对的版本工整的印刷格式呢?
有!笔者今天就写了这么一个小程序出来。代码量也不多,特此贴上来供有需要的同学参考学习。
2、实现
首先来说说笔者的需求:
笔者的需求是生成一个由随机数组成的指定行数与列数的二维数组。并且以文首图片所示的形式进行排版。
比如,我需要一个 32 行 4 列,数字范围在 0 ~ 64 之间的二维随机数组。
需求知道了,如何来实现呢? 完整的代码在文末。
首先来观察一下文首的示例图片,我们可以发现它的每一行都是有严格的规律的。
那么,我们就可以以 “行” 来入手,每次准备好一行的数据,再将它打印出来。
同时,为了排版能在任意文本编辑器中拥有同样的效果,字符之间的间隔统一使用空格字符而不是制表字符。
所以,第一步,我们先定义一个方法,用于封装这一功能。
static void generator(final int row, final int range) { }
我们需要可以动态指定这一二维数组的行及数值范围。需要注意的是,由于笔者是使用字节数组来表示一行数据的,字节数组在实例化时不能通过变量指定长度。因此在这个示例中,笔者就以一个 n 行 4 列的二维数组为例。如果同学实在是需要动态设定列数,可以通过集合来表示一行的数据。
第二步,我们定义一个 byte 数组,用来表示一行。
笔者这边的 range 范围为 0 ~ 255,因此按每个数字值都是 3 位数来算,一行中最长的长度形式就会有如下形式
{ 255, 255, 255, 255, }, //31
因此,我们的 byte 数组可以定义成如下形式的
static void generator(final int row, final int column, final int range) { byte[] line = new byte[40]; line[0] = '{'; line[1] = ' '; line[31] = ' '; line[32] = '}'; line[33] = ','; line[34] = ' '; line[35] = '/'; line[36] = '/'; line[39] = ' '; }
在这里,我们把一些固定的字符先填好。后面在生成随机数时再将相应的随机数坑位填充进行就可以了。
第三步,我们需要定义一个 StringBuilder 来添加每一行的数据,并定义一个随机数据生成实例。增加如下所示的定义即可。
StringBuilder sb = new StringBuilder();
Random rd = new Random();
第四步,就可以来做我们的核心算法了。不多废话,直接贴代码。
int randomValue = -1; int pos = 0; for(int i = 0; i < row; i++) { for(int j = 0; j < 4; j++) { randomValue = rd.nextInt(range); pos = j * 6 + 2; //pos 是每一列在前面的 byte 数组中的起始位置下标。
//下面的几个 if 是为了将数字转成可以直接打印出来的字符。 if(randomValue < 10) { line[pos] = (byte) (randomValue + '0'); line[pos + 1] = ','; line[pos + 2] = ' '; line[pos + 3] = ' '; line[pos + 4] = ' '; line[pos + 5] = ' '; }else if(randomValue < 100) { line[pos] = (byte) (randomValue / 10 + '0'); line[pos + 1] = (byte) (randomValue % 10 + '0'); line[pos + 2] = ','; line[pos + 3] = ' '; line[pos + 4] = ' '; line[pos + 5] = ' '; }else { line[pos] = (byte) (randomValue / 100 + '0'); line[pos + 1] = (byte) (randomValue % 100 / 10 + '0'); line[pos + 2] = (byte) (randomValue % 100 % 10 + '0'); line[pos + 3] = ','; line[pos + 4] = ' '; line[pos + 5] = ' '; } // 这段是为了每隔几行添加一个坐标注释,标明当前行是第几行。也是为了提升阅读体验。 if(i % 3 == 0) { if(i < 10) { line[35] = '/'; line[36] = '/'; line[37] = (byte) (i + '0'); line[38] = ' '; }else if(i < 100) { line[35] = '/'; line[36] = '/'; line[37] = (byte) (i / 10 + '0'); line[38] = (byte) (i % 10 + '0'); }else { line[35] = '/'; line[36] = '/'; } }else { line[35] = ' '; line[36] = ' '; line[37] = ' '; line[38] = ' '; } }// inner for -- end. // delete the last ',' if(i == row - 1) { line[33] = ' '; } sb.append(new String(line, 0, line.length)); }
最后,第五步,就没什么事了,直接将上一步得到的 sb.toString() 打印出来就是我们想要的数据的了。
System.out.println(sb.toString());
笔者这边试了一下,生成了几个 13 行 4 列的二维数组,效果如下图所示
大功告成,直接拷贝到需要用到它们的地方就可以了。
下面贴出完整代码。
import java.util.Random; public class TG { public static void main(String[] args) { generator(13, 255); } static void generator(final int row, final int range) { byte[] line = new byte[40]; line[0] = '{'; line[1] = ' '; line[31] = ' '; line[32] = '}'; line[33] = ','; line[34] = ' '; line[35] = '/'; line[36] = '/'; line[39] = ' '; StringBuilder sb = new StringBuilder(); Random rd = new Random(); int randomValue = -1; int pos = 0; for(int i = 0; i < row; i++) { for(int j = 0; j < 4; j++) { randomValue = rd.nextInt(range); pos = j * 6 + 2; if(randomValue < 10) { line[pos] = (byte) (randomValue + '0'); line[pos + 1] = ','; line[pos + 2] = ' '; line[pos + 3] = ' '; line[pos + 4] = ' '; line[pos + 5] = ' '; }else if(randomValue < 100) { line[pos] = (byte) (randomValue / 10 + '0'); line[pos + 1] = (byte) (randomValue % 10 + '0'); line[pos + 2] = ','; line[pos + 3] = ' '; line[pos + 4] = ' '; line[pos + 5] = ' '; }else { line[pos] = (byte) (randomValue / 100 + '0'); line[pos + 1] = (byte) (randomValue % 100 / 10 + '0'); line[pos + 2] = (byte) (randomValue % 100 % 10 + '0'); line[pos + 3] = ','; line[pos + 4] = ' '; line[pos + 5] = ' '; } // comment in tail. if(i % 3 == 0) { if(i < 10) { line[35] = '/'; line[36] = '/'; line[37] = (byte) (i + '0'); line[38] = ' '; }else if(i < 100) { line[35] = '/'; line[36] = '/'; line[37] = (byte) (i / 10 + '0'); line[38] = (byte) (i % 10 + '0'); }else { line[35] = '/'; line[36] = '/'; } }else { line[35] = ' '; line[36] = ' '; line[37] = ' '; line[38] = ' '; } }// inner for -- end. // delete the last ',' if(i == row - 1) { line[33] = ' '; } sb.append(new String(line, 0, line.length)); } System.out.println(sb.toString()); } }
对了,可以看到我所生成的二维数组中,每一行最后一列还是带有一个逗号分隔符。其实,为了美观,这个逗号分隔符最好不要出现。有兴趣的同学可以自行修改源码来实现这个需求啦。