如何使用Java Stream筛选非Kowalsk根的薪资记录并按降序高亮指定行
正确实现逻辑说明
原代码的缺陷
- 缺失薪资数值解析环节,无法实现按薪资降序排序的要求,直接
limit(3)是按文件遍历的原始顺序截取,不符合排序取前3的规则 - 未对解析异常场景做容错,遇到无有效薪资的行容易触发空指针或解析错误
- 没有目标行的高亮输出逻辑
实现流程
- 第一轮过滤:排除所有包含"Kowalsk"词根的行
- 第二轮过滤:仅保留带"zł"薪资标识的行,自动过滤"eksport danych"这类非业务数据行
- 数值解析:通过正则匹配提取合规行中zł前面的薪资数值,将原行内容与对应薪资值绑定,跳过无法解析出有效薪资的异常行
- 排序:将绑定薪资值的记录按数值从高到低降序排列,避免字符串排序带来的数值比对偏差
- 截取:取排序完成后的前3条记录
- 高亮输出:为选中的目标行添加高亮标记,支持终端ANSI高亮或文本层面的强调展示
完整可运行代码
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Comparator; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Stream; public class SalaryFilter { // 正则匹配zł前的薪资数值,兼容数值前后的空格场景 private static final Pattern SALARY_PATTERN = Pattern.compile("(\\d+\\.\\d+)\\s*zł"); // 终端高亮ANSI标记(亮黄色高亮,支持ANSI的终端环境可直接生效) private static final String HIGHLIGHT_PREFIX = "\033[1;33m"; private static final String HIGHLIGHT_SUFFIX = "\033[0m"; public static void main(String[] args) { String fileName = "earnings.txt"; try (Stream<String> lineStream = Files.lines(Paths.get(fileName))) { lineStream // 过滤含Kowalsk词根的行 .filter(line -> !line.contains("Kowalsk")) // 过滤无zł标识的行 .filter(line -> line.contains("zł")) // 解析薪资值,绑定原行内容 .map(line -> { Matcher matcher = SALARY_PATTERN.matcher(line); if (matcher.find()) { double salary = Double.parseDouble(matcher.group(1)); return new Object[]{salary, line}; } return null; }) // 过滤解析失败的空值 .filter(item -> item != null) // 按薪资数值降序排序 .sorted(Comparator.comparingDouble((Object[] item) -> (double) item[0]).reversed()) // 取排序后的前3条 .limit(3) // 输出高亮后的目标行 .forEach(item -> System.out.println(HIGHLIGHT_PREFIX + item[1] + HIGHLIGHT_SUFFIX)); } catch (IOException e) { e.printStackTrace(); } } }
适配说明
- 若输出环境不支持ANSI转义码(如旧版Windows cmd),可将高亮标记替换为*包裹行内容的文本强调格式
- 正则设计兼容源数据中薪资位置前后带空格的输入场景,降低解析失败概率
- 排序逻辑基于数值大小比对,不会出现字符串排序导致的"10000.00 zł"排到"9321.00 zł"后的逻辑错误
内容的提问来源于stack exchange,提问作者Jaro
相关产品推荐
相关产品推荐

