某个大厂的朋友跟爸妈抱怨今年钱不好挣,他妈直接回:“别的先不说,打工一年最少也得挣个四五十万吧。”
听完我人都愣了——这口气不像问收入,倒像是给上市公司定营收指标。
现实哪有这么整齐。别说四五十万,现在能稳住岗位、别被优化就已经算赢一半。大厂名头听着响,里边的人过得一点不轻松。家里一句“最少挣这么多”,员工看完估计连外卖都不敢点贵的那档了。
处理大日志最烦那种上来就 Files.readAllLines() 的写法。题目只要你拿第十行,结果把整个文件全读进内存,味儿就不对了。
第十行 这种题表面看着像字符串操作,真放到线上,我第一反应不是怎么取值,而是别为了 1 行把整个文件搬进来。
力扣195 的原版偏 Shell,用 sed -n '10p'、awk 'NR==10' 这类命令都能做。但你要是换成 Java,其实考的还是一个东西:顺着读,读到第 10 行就停,别多干。
先看我更愿意写的版本:
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class TenthLineReader {
public static String readTenthLine(Path path) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
String line;
int lineNo = 0;
while ((line = reader.readLine()) != null) {
lineNo++;
if (lineNo == 10) {
return line;
}
}
return "";
}
}
public static void main(String[] args) throws IOException {
Path path = Path.of("file.txt");
String ans = readTenthLine(path);
System.out.println(ans);
}
}
这段代码没耍花活,就是老老实实一行一行读。好处非常直接。
第一,不占多余内存。文件 10KB 和 10GB,对这段代码来说思路完全一样,最多只在内存里放当前这一行。
第二,能早停。读到第十行就返回,后面九千行、九百万行都不用管。很多人写代码喜欢“先全拿出来再说”,这道题刚好能把这种毛病照出来。
第三,边界清楚。文件不足十行怎么办?我这里返回空串。面试时你也可以返回 null,或者抛异常,但要提前讲清楚,别让调用方猜。
这个题还有个容易忽略的点:行号从 1 开始,不是从 0 开始。 这种地方最容易写成 if (lineNo == 9),然后自己还看半天没发现。题不难,错往往错在这种地方。
再看一种我不太喜欢的写法:
List<String> lines = Files.readAllLines(Path.of("file.txt"));
return lines.size() >= 10 ? lines.get(9) : "";
小文件跑起来也没问题,但这个思路放到真实项目里就有点糙了。尤其日志、导出文件、批处理文本,一旦文件大了,readAllLines() 就是在跟内存过不去。为了拿第十行,没必要把后面几万行都请进来。
所以这题真正该记住的,不是“怎么拿第十行”,而是这种判断顺序:先想读取方式,再想边界,最后才是第几行。
很多算法题一换到工程代码里,写法就该变。第十行 就是典型——别把它当成集合下标题,它本质上是个小型流式读取任务。思路顺了,这题代码能写得既短又干净;不顺的话,代码也能写得又慢又笨。