【问题标题】:How to concatenate all lists of objects (containing some text) within one big list through the means of stream()如何通过 stream() 将所有对象列表(包含一些文本)连接到一个大列表中
【发布时间】:2022-01-14 14:53:09
【问题描述】:

我得到: TextInfo 对象列表的列表。每个 TextInfo 对象都包含一段文本和一个用于返回文本的 toString 覆盖方法。通过 TextInfo 的 Y 值,我们可以得出 TextInfo 在同一行(自定义问题)的结论

我想要: 字符串列表。每个字符串是一个子列表的所有元素连接的结果。而且我想尽可能地利用流。

到目前为止:

List<String> allLinesByYCoordinate = groupAllTextLineByLineBasedOnY(allTextInfosOnPage);

public static List<String> groupAllTextLineByLineBasedOnY(List<TextInfo> allTextInfo) {
    Map<Object, List<TextInfo>> groupedtextInfosPerLine =  allTextInfo.stream().
                collect(Collectors.groupingBy(x -> x.getY()));
    List<String> allLines = new ArrayList<>();
    for (Map.Entry<Object, List<TextInfo>> groupedtextInfos: groupedtextInfosPerLine.entrySet()) {
        String temp = "";
        for (TextInfo textInfo: groupedtextInfos.getValue()) {
            temp += textInfo;
        }
        allLines.add(temp);
    }
    return allLines;
}

您可能同意 groupAllTextLineByLineBasedOnY 方法看起来有点过时。我正在尝试对大列表中的每个 TextInfo 列表执行串联,从而生成一个字符串列表,其中每个字符串曾经是 TextInfo 的列表

我希望能找到一个简洁的 stream() 解决方案

【问题讨论】:

    标签: java java-stream


    【解决方案1】:

    让我们一次重构一点。

    首先,你不应该在循环中构建字符串,因为它可能非常低效;改用 StringBuilder。但是,我们可以改为流式传输并收集到一个字符串中。还要注意这里我们使用 Map.values() 而不是在循环内调用 getValue()。

    public static List<String> groupAllTextLineByLineBasedOnY(List<TextInfo> allTextInfo) {
        Map<Object, List<TextInfo>> groupedtextInfosPerLine = allTextInfo.stream()
                        .collect(Collectors.groupingBy(x -> x.getY()));
        List<String> allLines = new ArrayList<>();
        for (List<TextInfo> groupedtextInfos: groupedtextInfosPerLine.values()) {
            allLines.add(groupedtextInfos.stream().map(Object::toString).collect(Collectors.joining()));
        }
        return allLines;
    }
    

    在接下来的重构中,我们可以去掉中间列表allLines,而是将 textInfos 流式传输并将它们收集到一个 List 中:

    public static List<String> groupAllTextLineByLineBasedOnY(List<TextInfo> allTextInfo) {
        Map<Object, List<TextInfo>> groupedtextInfosPerLine =  allTextInfo.stream()
                .collect(Collectors.groupingBy(x -> x.getY()));
    
        return groupedtextInfosPerLine.values().stream()
                .map(textInfos -> textInfos.stream().map(Object::toString).collect(Collectors.joining()))
                .toList();
    }
    

    最后,我们可以去掉 groupedtextInfosPerLine 变量:

    public static List<String> groupAllTextLineByLineBasedOnY(List<TextInfo> allTextInfo) {
        return allTextInfo.stream()
                .collect(Collectors.groupingBy(TextInfo::getY)).values().stream()
                .map(textInfos -> textInfos.stream().map(Object::toString).collect(Collectors.joining()))
                .toList();
    }
    

    【讨论】:

    • 精彩的解释。我将使用它(并努力理解它)。我最大的问题是如何连接字符串
    【解决方案2】:

    我认为您正在寻找这样的解决方案

    import java.util.Collection;
    import java.util.List;
    import java.util.TreeMap;
    import java.util.stream.Collectors;
    
    class Scratch {
        public static void main(String[] args) {
            // Setup some example data
            List<TextInfo> textInfos = List.of(
                    new TextInfo("line 3 a", 3),
                    new TextInfo("line 1 a", 1),
                    new TextInfo("line 2 a", 2),
                    new TextInfo("line 1 b", 1),
                    new TextInfo("line 3 b", 3),
                    new TextInfo("line 1 c", 1)
            );
            
            // This is the actual answer
            Collection<String> allLines = textInfos.stream()
                    .collect(Collectors.toMap(
                            TextInfo::getY, // line number as key
                            TextInfo::toString, // convert TextInfo to String
                            (a, b) -> a + b, // Merge TextInfo on the same line
                            TreeMap::new)) // Ensure in order
                    .values();
    
            // You would return allLines from the method
            System.out.println(allLines);
        }
    
        static class TextInfo {
            String text;
            int y;
    
            public TextInfo(String text, int y) {
                this.text = text;
                this.y = y;
            }
    
            public int getY() { return y; }
    
            @Override
            public String toString() { return text; }
        }
    }
    

    如果你运行你打印的代码

    [line 1 aline 1 bline 1 c, line 2 a, line 3 aline 3 b]
    

    【讨论】:

      猜你喜欢
      • 2020-08-14
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2021-02-06
      • 2021-09-24
      • 2014-02-17
      • 2017-03-05
      • 2022-09-28
      相关资源
      最近更新 更多