Как легко и аккуратно распечатать несколько объектов, используя метод toString, которые также выровнены? - PullRequest
3 голосов
/ 07 мая 2019

У меня есть ArrayList членов, каждый из которых имеет свою собственную информацию, включая имя, возраст, дату рождения и т. Д., Которая вызывается методом toString при распечатке на терминал.

Вот код:

@Override
    public String toString() {
        return "|ID: " + id + "| Name: " + name + "| Age: " + 
              calculateAge(age, LocalDate.now()) + "| Tlf.: " + tlfNo + "| Active: " + 
              activeMember + "| Next payment: " + nextPayment + "|";
    }

А вот и вывод:

|ID: 12| Name: Casper| Age: 49| Tlf.: 12345678| Active: true| Next payment: 2018-02-12|
|ID: 13| Name: Allan| Age: 69| Tlf.: 12345678| Active: true| Next payment: 2018-01-12|
|ID: 16| Name: Christina| Age: 100| Tlf.: 12345678| Active: false| Next payment: 2018-02-04|
|ID: 19| Name: RICK| Age: 49| Tlf.: 12345678| Active: false| Next payment: 2018-04-14|

Как мне заставить разные части информации выравниваться друг над другом?

Ответы [ 3 ]

1 голос
/ 07 мая 2019

Вы можете сделать что-то вроде:

 public String toString() {
        return String.format("|id: %10d |Name: %30s| Age: %02d | Tlf.: %d| Active: %s| Next Payment: %s |", id, getNameTrimmed() , age , tlfNo ,    activeMember, nextPayment );
 }

 private  String getNameTrimmed(){
    if(name.length()>30) {
        return name.substring(0,27)+"...";
    }
    return name;
}

Таким образом, идентификатор будет иметь 10 символов (он все равно будет нарушать формат, если у вас более длинные идентификаторы) Имя будет иметь 30, поэтому вам нужно добавить метод, чтобы дать вам 30 символов имени

1 голос
/ 07 мая 2019

Вы можете создать метод для этого, так как toString просто не будет работать:

static String printPojos(Pojo... pojos) {
    int maxName = Arrays.stream(pojos)
                        .map(Pojo::getName)
                        .mapToInt(String::length)
                        .max()
                        .orElse(0);

    int maxId = Arrays.stream(pojos)
                      .mapToInt(x -> x.getName().length())
                      .max()
                      .orElse(0);

    StringJoiner result = new StringJoiner("\n");
    for (Pojo pojo : pojos) {
        StringJoiner sj = new StringJoiner("|");
        sj.add("ID: " + Strings.padEnd(Integer.toString(pojo.getId()), maxId, ' '));
        sj.add(" Name: " + Strings.padEnd(pojo.getName(), maxName, ' '));
        sj.add(" Age: " + Strings.padEnd(Integer.toString(pojo.getAge()), 3, ' '));
        sj.add(" Active: " + Strings.padEnd(Boolean.toString(pojo.isActive()), 5, ' '));

        result.merge(sj);
    }

    return result.toString();
}

Я использую Strings::padEnd (из guava, но это довольно легко написать дажебез внешней библиотеки).

Pojo в моем случае выглядит так:

static class Pojo {

    private final int id;
    private final String name;
    private final int age;
    private final boolean active;

    // constructor, getters

}

И результат выглядит так:

    Pojo one = new Pojo("Casper", 49, true, 1);
    Pojo two = new Pojo("Allan", 100, true, 10_000);

    System.out.println(printPojos(one, two));



ID: 1    | Name: Casper| Age: 49 | Active: true 
ID: 10000| Name: Allan | Age: 100| Active: true 
0 голосов
/ 07 мая 2019

У меня есть простая реализация для вашей задачи, которая не требует внешних библиотек.Если вы хотите использовать внешние библиотеки, есть достаточно методов, например, в Apache-Commons или Guava.Возможно, это можно сделать умнее, но это поможет:

class Member {

  String id;
  String name;
  int age;
  LocalDate date;
  int tlfNo;
  boolean activeMember;
  LocalDate nextPayment;

  public Member(String id, String name, int age, int tlfNo, boolean activeMember, LocalDate nextPayment) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.tlfNo = tlfNo;
    this.activeMember = activeMember;
    this.nextPayment = nextPayment;
  }

  @Override
  public String toString() {
    return String.format("|ID: %s| Name: %s| Age: %s| Tlf.: %s| Active: %s| Next payment: %s|", 
      doFormat(id, "id", 10), doFormat(name, "name", 10),             
      doFormat(String.valueOf(age), "age", 10), 
      doFormat(String.valueOf(tlfNo), "tlfNo", 10), 
      doFormat(String.valueOf(activeMember), "active", 10),             
      doFormat(nextPayment.toString(), "nextPayment", 20));
  }

  String doFormat(String value, String fieldName, int maxLenght) {
    if (value.length() > maxLenght) {
      throw new IllegalArgumentException(String.format("cannot format string longer than %s for %s, value = %s", maxLenght, fieldName, value));
    }
    return padLeftSpaces(value, maxLenght);
  }

  public String padtLefSpaces(String inputString, int length) {
    if (inputString.length() >= length) {
      return inputString;
    }
    StringBuilder sb = new StringBuilder();
    while (sb.length() < length - inputString.length()) {
      sb.append(' ');
    }
    sb.append(inputString);

    return sb.toString();
  }
}

Идея состоит в том, что вы заполняете все поля пробелами и заменяете только те, которые заняты.Левый метод заимствован из bealdung

...