Skip to main content
added 73 characters in body
Source Link
candied_orange
  • 840
  • 1
  • 7
  • 21

but is that as good asBy waiting until all the lines have been added before printing it could be?can figure out the width each column needs.

but is that as good as it could be?

By waiting until all the lines have been added before printing it can figure out the width each column needs.

added 8 characters in body
Source Link
candied_orange
  • 840
  • 1
  • 7
  • 21

but is that as good as it could be? 

Looking for a code review to reveal problems. Anything from better names to fewer bugs to better ideas.

but is that as good as it could be? Looking for a code review to reveal problems. Anything from better names to fewer bugs to better ideas.

but is that as good as it could be? 

Looking for a code review to reveal problems. Anything from better names to fewer bugs to better ideas.

Source Link
candied_orange
  • 840
  • 1
  • 7
  • 21

Print columns of text without hard coding the width

If you'd like to print this:

One Two Three Four
 1   2    3    4  

using this:

new Columns()
    .withColumnSeparator(" ")
    .withPad(" ")
    .alignCenter()
    .addLine("One", "Two", "Three", "Four")
    .addLine("1", "2", "3", "4")
    .print()
;

all you need is this:

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

public class Columns {

    List<List<String>> lines = new ArrayList<>();
    List<Integer> maxLengths = new ArrayList<>();
    int numColumns;
    int oldLength;
    boolean firstCall = true;
    String columnSeparator = " ";
    String pad = " ";
    BiFunction<String, String, String> align = (word, pad) -> word += pad;

    public Columns addLine(String... line) {

        if (firstCall){
            for(int column = 0; column < line.length; column++) {
                maxLengths.add(0);
            }
            oldLength = line.length;
        }
        
        if (oldLength != line.length) {
            throw new IllegalArgumentException();
        }

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

        lines.add( Arrays.asList(line) );
        firstCall = false;
        return this;
    }

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

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

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

    public Columns withColumnSeparator(String columnSeparator){
        this.columnSeparator = columnSeparator;
        return this;
    }
        
    public Columns withPad(String pad){
        this.pad = pad;
        return this;
    }
    
    public Columns alignLeft(){
        align = (word, pad) -> word = word + pad;
        return this;
    }

    public Columns alignRight(){
        align = (word, pad) -> word = pad + word;
        return this;
    }

    public Columns alignCenter(){
        align = (word, pad) -> {
            return (word.length() % 2 == 0) 
                ? pad + word
                : word + pad
            ;
        };
        return this;
    }
}

but is that as good as it could be? Looking for a code review to reveal problems. Anything from better names to fewer bugs to better ideas.