在Java中,有没有一种简单的方法将两列输出到控制台?

40

正如标题所说,有没有一种简单的方法在Java中将两列输出到控制台?

我知道可以使用\t,但是当使用printf时,我还没有找到基于特定列进行间隔的方法。

3个回答

63

使用相同值设置宽度和精度说明符。这将对太短的字符串进行填充,并截断过长的字符串。'-' 标志将左对齐列中的值。

System.out.printf("%-30.30s  %-30.30s%n", v1, v2);

3
有关Java字符串格式化的更多详细信息,请参阅文档 - Rodrigue
2
%-30.30s%-30s 有什么区别? - John R Perry
3
使用 .30 时,最大的字段宽度为 30。超过该长度的值将被截断。 - erickson
但是对于这种语句,我们不能应用那个方法。str += "\t " + item.getName() + " [" + item.getValue() + "]" + "\t" + item.getDescription()+ "\n"; 针对这种情况,我们该怎么办? - chamzz.dot
@chamzz.dot 在连接字符串时请使用String.format()。看起来你正在循环中使用它,这可能会导致二次时间复杂度(换句话说,这是不好的)。相反,将str设为一个StringBuilder并放在循环外部,在循环内部使用append()方法添加每个String.format()调用的结果。 - erickson

32

我没有使用Formatter类,而是这样做的:

 
System.out.printf("%-10s %-10s %-10s\n", "osne", "two", "thredsfe");
System.out.printf("%-10s %-10s %-10s\n", "one", "tdsfwo", "thsdfree");
System.out.printf("%-10s %-10s %-10s\n", "onsdfe", "twdfo", "three");
System.out.printf("%-10s %-10s %-10s\n", "odsfne", "twsdfo", "thdfree");
System.out.printf("%-10s %-10s %-10s\n", "osdne", "twdfo", "three");
System.out.printf("%-10s %-10s %-10s\n", "odsfne", "tdfwo", "three");

输出结果为:

osne       two        thredsfe  
one        tdsfwo     thsdfree  
onsdfe     twdfo      three     
odsfne     twsdfo     thdfree   
osdne      twdfo      three     
odsfne     tdfwo      three     

16

虽然回答晚了一些,但如果您不想硬编码宽度,那么可以考虑像这样工作:

public static void main(String[] args) {
    new Columns()
        .addLine("One", "Two", "Three", "Four")
        .addLine("1", "2", "3", "4")
        .print()
    ;
}

并显示:

One Two Three Four 
1   2   3     4    

只需要这么做:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;  

public class Columns {

    List<List<String>> lines = new ArrayList<>();
    List<Integer> maxLengths = new ArrayList<>();
    int numColumns = -1;

    public Columns addLine(String... line) {

        if (numColumns == -1){
            numColumns = line.length;
            for(int column = 0; column < numColumns; column++) {
                maxLengths.add(0);
            }
        }

        if (numColumns != line.length) {
            throw new IllegalArgumentException();
        }

        for(int column = 0; column < numColumns; column++) {
            int length = Math
                .max( 
                    maxLengths.get(column), 
                    line[column].length() 
                )
            ;
            maxLengths.set( column, length );
        }

        lines.add( Arrays.asList(line) );

        return this;
    }

    public void print(){
        System.out.println( toString() );
    }

    public String toString(){
        String result = "";
        for(List<String> line : lines) {
            for(int i = 0; i < numColumns; i++) {
                result += pad( line.get(i), maxLengths.get(i) + 1 );                
            }
            result += System.lineSeparator();
        }
        return result;
    }

    private String pad(String word, int newLength){
        while (word.length() < newLength) {
            word += " ";            
        }       
        return word;
    }
}

由于它只有在获取所有行后才会打印,因此可以学习如何调整列的宽度。无需硬编码宽度。


我在Java方面有点新手,对于方法之间的通信感到困惑。pad()System.lineSeparator()以及这一行代码maxLengths.set( i, Math.max( maxLengths.get(i), line[i].length() )具体是做什么的?抱歉问题比较多,我只是不喜欢使用自己不完全了解其工作原理的代码。 - Wax
@Wax 好的。更好了吗? - candied_orange
这正是我一直在寻找的。 虽然使用字符串连接而不是 StringBuilder 在这里更好吗? 我知道这个解决方案的目的不是针对这个问题,但仍然最好在这里使用 StringBuilder,因为字符串连接非常昂贵。 - Himanshu Dabas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接