string.lines() 返回的是stream流,按unicode行终止符解析并丢弃所有终止符,不依赖系统换行符,空字符串返回空流,无需close,语义上仅表示“有意义的行”。

String.lines() 返回的是什么流?
它返回 Stream<string></string>,不是 List,也不是 String[]。这意味着你不能直接索引、也不能靠 get(0) 取第一行——必须用流式操作处理。
常见错误现象:String.lines().get(0) 编译失败;String.lines().toArray() 返回 Object[],强转 String[] 会抛 ClassCastException。
- 要用
collect(Collectors.toList())转成List<string></string>才能随机访问 - 如果只取前几行,优先用
limit(n),避免全量加载大文本 - 注意:空字符串
""调用.lines()返回空流(0 个元素),不是含一个空字符串的流
换行符识别规则和平台兼容性
String.lines() 按 Unicode 行终止符规范解析,支持
、
、
、u2028(LINE SEPARATOR)、u2029(PARAGRAPH SEPARATOR)等,不依赖系统 line.separator。
使用场景:读取跨平台日志文件、解析 HTTP 响应体、处理用户粘贴的富文本(含 Mac/Linux/Windows 混合换行)时更鲁棒。
立即学习“Java免费学习笔记(深入)”;
- Windows 文件用
,Linux 用,Java 11+ 的lines()全部识别,无需预处理 - 但注意:
单独出现(旧 Mac)也会被识别为一行结束,可能意外切分内容 - 性能影响:比手写
split(" ")稍慢(因要多匹配几种终止符),但对普通文本可忽略
与 split("\R") 的关键区别
String.lines() 和正则 split("\R") 都能按换行切分,但行为不同:前者丢弃所有行终止符,后者在某些边界下可能产生空字符串。
常见错误现象:用 split("\R") 处理末尾带换行的字符串(如 "a
b
"),得到 ["a", "b", ""];而 lines() 只返回 ["a", "b"]。
-
\R是 Java 8+ 正则中的换行符通配,但split()对结尾空段默认保留(除非加-1参数) -
lines()始终忽略空白行(包括纯终止符构成的“行”),语义更贴近“有意义的行” - 若需保留末尾空行,别用
lines()—— 改用split(" | | ", -1)
流未关闭的风险和提前终止场景
String.lines() 返回的流是顺序、非并发、无状态的,但它仍是 AutoCloseable。不过官方文档明确说:**无需也不应该手动 close** —— 它没有底层资源要释放。
容易踩的坑:在 try-with-resources 中包裹 lines() 流,不仅多余,还可能干扰流的短路操作(如 findFirst())。
- 调用
findFirst()或anyMatch()后流自动终止,不会遍历全文本 - 但如果你在 lambda 里抛异常,且没捕获,流会中断,但无副作用
- 真正要注意的是:别把它和
Files.lines()混淆——后者读文件流,必须 close
事情说清了就结束。记住:它不是语法糖,是语义明确的行抽象;用错地方(比如想留空行或需要索引)反而比 split 更麻烦。










