在将值打印到"漂亮的表视图";时尚
我的测试数据集代码是:
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/rightPad
做sb.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
更改为" | "
以具有更大的间距,或者将" "
更改为仅使用空格或空字符串(根据需要(。您还可以将keyWidth
和valueWidth
适应现实生活场景。
上面的解决方案在循环中使用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");