找到一段开始记录时,我有一段代码将文件“分成”几块。
List<StringBuilder> list = new ArrayList<>();
StringBuilder jc = null;
try (BufferedReader br = Files.newBufferedReader(Paths.get("")) {
for (String line = br.readLine(); line != null; line = br.readLine()) {
if (line.startsWith("REQ00")) {
jc = new StringBuilder();
list.add(jc);
}
jc.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
有什么办法可以将此代码“转换”为Java 8 Stream方法吗?
最佳答案
使用正确的工具完成工作。使用Scanner
,就像
List<String> list = new ArrayList<>();
try(Scanner s = new Scanner(Paths.get(path))) {
s.useDelimiter(Pattern.compile("^(?=REQ00)", Pattern.MULTILINE));
while(s.hasNext()) list.add(s.next());
} catch (IOException e) {
e.printStackTrace();
}
现在,您的代码具有创建
StringBuilder
且不保留换行符的特殊要求。因此,扩展版本为:List<StringBuilder> list = new ArrayList<>();
try(Scanner s = new Scanner(Paths.get(path))) {
s.useDelimiter(Pattern.compile("^(?=REQ00)", Pattern.MULTILINE));
while(s.hasNext()) list.add(new StringBuilder(s.next().replaceAll("\\R", "")));
} catch (IOException e) {
e.printStackTrace();
}
一个更有效的变体是
List<StringBuilder> list = new ArrayList<>();
try(Scanner s = new Scanner(Paths.get(path))) {
s.useDelimiter(Pattern.compile("^(?=REQ00)", Pattern.MULTILINE));
while(s.hasNext()) list.add(toStringBuilderWithoutLinebreaks(s.next()));
} catch (IOException e) {
e.printStackTrace();
}
…
static final Pattern LINE_BREAK = Pattern.compile("\\R");
static StringBuilder toStringBuilderWithoutLinebreaks(String s) {
Matcher m = LINE_BREAK.matcher(s);
if(!m.find()) return new StringBuilder(s);
StringBuilder sb = new StringBuilder(s.length());
int last = 0;
do { sb.append(s, last, m.start()); last = m.end(); } while(m.find());
return sb.append(s, last, s.length());
}
从Java 9开始,您还可以对其使用
Stream
操作:List<StringBuilder> list;
try(Scanner s = new Scanner(Paths.get(path))) {
list = s.useDelimiter(Pattern.compile("^(?=REQ00)", Pattern.MULTILINE))
.tokens()
.map(string -> toStringBuilderWithoutLinebreaks(string))
.collect(Collectors.toList());
} catch (IOException e) {
e.printStackTrace();
list = List.of();
}