如何通过 stream() 将所有对象列表(包含一些文本)连接到一个大列表中
How to concatenate all lists of objects (containing some text) within one big list through the means of stream()
我得到:
TextInfo 对象列表的列表。每个 TextInfo 对象都包含一段文本和 return 文本的 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() 解决方案
让我们一次重构一点。
首先,你永远不应该在循环中构建一个字符串,因为它可能非常低效;请改用 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 并将它们收集到一个列表中:
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();
}
我认为您正在寻找这样的解决方案
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]
我得到: TextInfo 对象列表的列表。每个 TextInfo 对象都包含一段文本和 return 文本的 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() 解决方案
让我们一次重构一点。
首先,你永远不应该在循环中构建一个字符串,因为它可能非常低效;请改用 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 并将它们收集到一个列表中:
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();
}
我认为您正在寻找这样的解决方案
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]