在跨越列表时使用 FlatMap 和 Collector 而不是 forEach 和 StringBuilder

问题描述 投票:0回答:1

我有一些工作代码可以变成这个:

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    

但是在尝试使用这也是工作代码改进它时,并按照here给出的建议,我尝试替换这个工作

toString()
代码:

public String toString(){
    
    final StringBuilder result = new StringBuilder();
    final int rows = columns.get(0).size();

    IntStream
        .range(0, rows)
        .forEach( 
            row -> {
                result
                    .append( 
                        columns
                        .stream()
                        .map(col -> col.getCell(row))
                        .collect( Collectors.joining(columnSeparator) )
                    )
                ;
                result.append( System.lineSeparator() );
            }
        )
    ;

    return result.toString();
}

使用这个损坏的

toString()
代码:正在关注这个

public String toString(){
    
    final int rows = columns.get(0).size();
    
    return IntStream
        .range(0, rows)
        .flatMap(row -> columns
            .stream()
            .map( col -> col.getCell(row) )
            .collect( Collectors.joining(columnSeparator) )
        )
        .collect( Collectors.joining( System.lineSeparator() ) )
    ;
}

只看到这个:

Columns.java:81: error: incompatible types: bad return type in lambda expression
                .collect( Collectors.joining(columnSeparator) )
                        ^
    inference variable R has incompatible bounds
      equality constraints: String
      lower bounds: IntStream,Object
  where R,A,T are type-variables:
    R extends Object declared in method <R,A>collect(Collector<? super T,A,R>)
    A extends Object declared in method <R,A>collect(Collector<? super T,A,R>)
    T extends Object declared in interface Stream
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

我只能说,老鼠。


如果你是那种讨厌点击链接的人,这里是你错过的重点:

private final List<Column> columns = new ArrayList<>();

Column
类中我们发现

public String getCell(int row){
    return padCell( words.get(row), maxLength );
}

我得到的建议是:“将 toString 中的

StringBuilder
替换为另一个加入的
Collector
。”

toString
试图逐行遍历这些列,连接它在每个列中找到的字符串的填充单元格。在转到下一行之前完成所有列中的一行单元格。

是的,我知道一个简单的双循环可以做到这一点,但那有什么乐趣呢?

老实说,它确实有效,但在侧面留下了不需要的列分隔符,这让我很烦

java java-stream tostring
1个回答
1
投票

您的外部流调用

flatMap()
,它应该将每个元素扩展为一个流(在本例中为
IntStream
)并将结果展平为一个流。它失败了,因为提供的函数返回单个字符串而不是流。由于结果是一对一的,你只需要一个普通的映射操作将每一行转换成一个字符串:

return IntStream
    .range(0, rows)
    .mapToObj(row -> columns
        .stream()
        .map( col -> col.getCell(row) )
        .collect( Collectors.joining(columnSeparator) )
    )
    .collect( Collectors.joining( System.lineSeparator() ) )
;
© www.soinside.com 2019 - 2024. All rights reserved.