在漂亮的打印表视图java中排列值



在将值打印到"漂亮的表视图";时尚

我的测试数据集代码是:

Map<Integer, List<Boolean>> map = new HashMap<>();
Random r = new Random(System.currentTimeMillis());
map.put(1000 + r.nextInt(50000), Arrays.asList(true, false, false));
map.put(100 + r.nextInt(50000), Arrays.asList(false, false, false));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, true, false));
map.put(100 + r.nextInt(50000), Arrays.asList(true, false, true));
map.put(1000 + r.nextInt(50000), Arrays.asList(false, true, true));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, false, false));
map.put(1000 + r.nextInt(50000), Arrays.asList(false, false, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(true, true, false));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, false, true));
map.put(1000 + r.nextInt(5000), Arrays.asList(true, false, false));
map.put(100 + r.nextInt(50000), Arrays.asList(false, false, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(true, true, false));
map.put(1000 + r.nextInt(5000), Arrays.asList(true, false, true));
map.put(100 + r.nextInt(50000), Arrays.asList(false, true, true));
map.put(100 + r.nextInt(5000), Arrays.asList(true, false, false));
map.put(1000 + r.nextInt(50000), Arrays.asList(false, false, false));
map.put(1000 + r.nextInt(5000), Arrays.asList(true, true, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(true, false, true));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, false, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(false, false, false));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, true, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(true, false, true));
map.put(1000 + r.nextInt(5000), Arrays.asList(false, true, true));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, false, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(false, false, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(true, true, false));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, false, true));
map.put(10000 + r.nextInt(50000), Arrays.asList(true, false, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(false, false, false));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, true, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(true, false, true));
map.put(100 + r.nextInt(50000), Arrays.asList(false, true, true));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, false, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(false, false, false));
map.put(10000 + r.nextInt(50000), Arrays.asList(true, true, false));
map.put(100 + r.nextInt(50000), Arrays.asList(true, false, true));
map.put(1000 + r.nextInt(50000), Arrays.asList(true, false, true));
int counter = 0;
StringBuilder sb = new StringBuilder();
for (Map.Entry<Integer, List<Boolean>> entry : map.entrySet()) {
sb.append(entry.getKey() + " = " + entry.getValue() + " t");
if (counter == 5) {
System.out.println(sb.toString());
counter = 0;
sb.setLength(0);
}
counter++;
}

我使用的是测试数据集,因为真实的数据太多,更容易在较小的批次中工作,但输出看起来完全像:

30336 = [true, false, true]     2820 = [true, false, false]     17029 = [false, false, false]   10183 = [true, true, false]     14600 = [true, true, false]     9741 = [true, false, true]  
32717 = [true, true, false]     3664 = [true, true, false]  22610 = [true, false, true]     49618 = [true, true, false]     43476 = [true, false, true]     
4439 = [true, false, true]  1816 = [false, false, false]    57562 = [true, false, true]     23450 = [false, true, true]     21018 = [true, false, false]    
35291 = [false, false, false]   40923 = [true, false, false]    5342 = [true, true, false]  32353 = [false, false, false]   48098 = [true, true, false]     
41442 = [false, false, false]   39269 = [true, true, false]     11623 = [false, true, true]     45031 = [true, false, false]    23720 = [true, false, false]    
23209 = [false, false, false]   37419 = [false, true, true]     26798 = [true, false, true]     1454 = [false, true, true]  2544 = [true, false, false]     
12080 = [true, false, false]    26418 = [false, false, false]   24052 = [true, false, true]     50293 = [false, false, false]   25720 = [true, false, true] 

关键的Integer范围很大,这让我认为它没有正确排列;false";比单词"长;真";,因此,如果某些条目的值是假多于真,那么它也会把排列搞砸。但是,有没有一种万无一失或简单的方法来解决这个问题?我试过用StringUtils.leftPad/rightPadsb.append(entry.getKey() + " = " + entry.getValue() + " t");,但结果相似,几乎是一条直线,但锯齿状。

请注意,将StringBuilder与等字符串串联混合是不一致的

sb.append(entry.getKey() + " = " + entry.getValue() + " t");

相反,应按预期使用StringBuilder,例如

sb.append(entry.getKey()).append(" = ").append(entry.getValue()).append(" t");

从那里,。将调用链分解为单独的语句并根据需要插入填充只是一小步:

final String columnSeparator = "|";
final int keyWidth = 6, valueWidth = "false, ".length() * 3;
int counter = 0;
StringBuilder sb = new StringBuilder();
for (Map.Entry<Integer, List<Boolean>> entry : map.entrySet()) {
int colStart = sb.length(), colEnd = colStart + keyWidth;
sb.append((int)entry.getKey());
while(sb.length() < colEnd) sb.insert(colStart, ' '); // right aligned
sb.append(" = ");
colEnd = sb.length() + valueWidth;
sb.append(entry.getValue());
while(sb.length() < colEnd) sb.append(' '); // left aligned
if(counter == 5) {
sb.append(System.lineSeparator());
counter = 0;
}
else {
sb.append(columnSeparator);
counter++;
}
}
if(counter != 0) {
sb.setLength(sb.length() - columnSeparator.length());
sb.append(System.lineSeparator());
}
System.out.append(sb);

产生类似的输出

14339 = [false, false, false]|  4869 = [true, false, false] | 17669 = [true, false, false] |  3526 = [false, false, false]|  1864 = [false, true, true]  |  9224 = [false, true, true]  
30152 = [true, true, false]  | 19273 = [false, false, false]| 49547 = [true, true, false]  |  5391 = [true, false, false] |  4943 = [false, false, false]| 39311 = [true, false, true]  
7889 = [true, false, true]  | 31893 = [false, false, false]| 49174 = [true, true, false]  |  3094 = [true, false, true]  | 16854 = [true, false, true]  | 27094 = [true, false, false] 
46234 = [true, true, false]  | 22751 = [true, false, false] | 58339 = [false, false, false]| 49700 = [true, false, true]  | 44901 = [true, false, false] | 49254 = [true, false, true]  
24230 = [true, true, false]  | 45799 = [true, true, false]  | 39591 = [true, false, true]  | 17450 = [false, false, false]| 30893 = [true, false, true]  | 14189 = [true, false, true]  
33583 = [false, true, true]  | 29365 = [false, false, false]|  5563 = [false, true, true]  | 17341 = [true, true, false]  |  5245 = [true, true, false]  | 18302 = [true, false, false] 
4223 = [true, false, false] 

您可以将columnSeparator更改为" | "以具有更大的间距,或者将" "更改为仅使用空格或空字符串(根据需要(。您还可以将keyWidthvalueWidth适应现实生活场景。


上面的解决方案在循环中使用sb.insert,只有当我们知道必须移位的字符数很小(这是一个整数(并且迭代次数也很小(这里,我们有四个或五个数字,所以它最多迭代两次(时,这才是可行的。

当实际密钥长度之间的差异较大时,可以通过在for循环之前插入String pad = " ".repeat(keyWidth);并替换来消除循环

while(sb.length() < colEnd) sb.insert(colStart, ' ');

带有

if(sb.length() < colEnd) sb.insert(colStart, pad, 0, colEnd - sb.length());

当您还将密钥类型更改为可能产生较大字符串的类型时,您可以通过替换来完全避免insert

sb.append((int)entry.getKey());
while(sb.length() < colEnd) sb.insert(colStart, ' '); // right aligned

带有

String key = String.valueOf(entry.getKey());
if(key.length() < keyWidth) sb.append(pad, 0, keyWidth - key.length());
sb.append(key);

但这只会为那些无论如何都必须通过其toString()方法附加的对象带来回报,而不是为那些在没有必须复制的中间字符串的情况下通过append(int)附加的Integer密钥带来回报。


如果你有固定的列宽,并且想要一个简单的解决方案,你可以使用

int counter = 0;
for(Map.Entry<Integer, List<Boolean>> entry : map.entrySet()) {
System.out.printf(++counter%5 != 0? "%6d = %-21s|": "%6d = %21s%n",
entry.getKey(), entry.getValue());
}
if(counter % 5 != 0) System.out.println();

尝试

sb.append(entry.getKey() + "t=t" + entry.getValue() + " t"); 

最新更新