如何在Java中返回一个Collector,它形成了一个特殊的可打印字符串?

rseugnpd  于 2023-06-28  发布在  Java
关注(0)|答案(1)|浏览(91)

我一直在尝试编写一个名为printableStringCollector的方法,它基本上返回一个收集器,该收集器形成一个特殊的可打印String,如下所述-
可打印字符串规格
它是一个多行字符串,包含所有结果、总值和标记的格式化表格。表格的格式应满足以下要求:

  • 需要标头。
  • 列宽取决于值的长度。
  • 行按学生的姓氏排序。
  • 列按任务名称排序。
  • 双精度值显示为小数点后2位。
  • “标记”列的值由平均总分定义。

示例:

Student........|Phalaxing |Shieldwalling |Tercioing |Wedging |Total |Mark |
Eco Betty......|0 ........|83............|89........|59......|57.75 |F ...|
Lodbrok Johnny |61 .......|92............|67........|0.......|55.00 |F....|
Paige Umberto..|75....... |94............|0.........|52......|55.25 |F....|
Average........|45.33.....|89.67.........|52.00.....|37.00...|56.00 |F....|
  • 为了更好的视觉表现而写了点

有人能帮我实现这个方法吗?

public Collector<CourseResult, ?, String> printableStringCollector() {

}

CourseResult类:

public class CourseResult {
    private final Person person;
    private final Map<String, Integer> taskResults;

    public CourseResult(final Person person, final Map<String, Integer> taskResults) {
        this.person = person;
        this.taskResults = taskResults;
    }

    public Person getPerson() {
        return person;
    }

    public Map<String, Integer> getTaskResults() {
        return taskResults;
    }
}

Person类:

public class Person {
    private final String firstName;
    private final String lastName;
    private final int age;

    public Person(String firstName, String lastName, int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        final Person person = (Person) o;
        return age == person.age &&
                      Objects.equals(firstName, person.firstName) &&
                      Objects.equals(lastName, person.lastName);
    }

    @Override
    public int hashCode() {
        return Objects.hash(firstName, lastName, age);
    }

    @Override
    public String toString() {
        return new StringJoiner(", ", Person.class.getSimpleName() + "[", "]")
                .add("firstName='" + firstName + "'")
                .add("lastName='" + lastName + "'")
                .add("age=" + age)
                .toString();
    }
}
hgqdbh6s

hgqdbh6s1#

大多数情况下,当我需要创建一个自定义收集器时,我会为它创建一个新类,并为其提供方法accumulatecombinefinish,以匹配收集器中的操作符。这个类可以做任何需要做的事情。例如,如果finish是可选的:

Collector<T, ?, R> collector = Collector.of(
        MyCollector::new,
        MyCollector::accumulate,
        MyCollector::combine,
        MyCollector::finish);

在您的情况下,您将不得不流两次,因为收集器需要在输出任何内容之前看到每个学生姓名的长度。收集器将存储其CourseResult示例以及最大长度。然后,它将再次流式传输,并使用String.format来完成添加填充的所有艰苦工作(例如"%" + maxNameLength + "s | %10s | ...")。
finish方法看起来像这样(简化):

public String finish() {
    String header = "...\n"; // use same padding
    String pattern = "...";
    return results.stream()
            .map(result -> String.format(pattern, result.getPerson().getName(), ...)
            .collect(Collectors.joining("\n", header, ""));
}

我不会对标题使用完全相同的模式,因为行包含标题不包含的数字。

相关问题