使用Comparator.reversed()反转Stream排序:高频词统计时的排序反向及引用报错问题
报错根因解析
你遇到的Non-static method cannot be referenced from a static context编译错误,核心源于对reversed()方法的属性认知偏差和类型推断失效:
reversed()是Comparator接口的实例方法,必须依附于已经生成好的比较器实例调用,不能直接当成Comparator类的静态方法直接调用。很多新手写代码时误把.reversed()放在Comparator.后面直接调用,就会触发这个报错——毕竟静态上下文里只能直接调用类的静态方法,无法直接访问实例方法。- 你参考的示例能正常运行,本质是示例代码里的类型推断链路完整,能自动识别比较器的泛型类型;而你当前代码里的
Map.Entry没有明确指定泛型参数,被编译器当成无类型的原始类,导致方法引用Map.Entry::getValue的归属识别错误,进一步放大了这个语法问题。
另外你之前遇到的“排序结果和预期反向”,本质是Comparator.comparing()默认按字段值从小到大排序:按频次排序时,数字越小的频次越排在前面,刚好和你要的“高频在前”的顺序完全相反。
适合新手Stream写法的修正方案
不需要复杂的语法调整,只需要在比较器位置明确指定泛型类型,修正类型推断的问题,就能正常调用反转逻辑:
- 优先用更不容易踩坑的静态反向比较器写法,避免混淆实例/静态方法的调用规则,可直接把原来的比较器代码替换为
Comparator.comparingLong(Map.Entry<String, Long>::getValue).reversed()
或者更直白的写法,直接在比较器的参数里指定反向规则:Comparator.comparing(Map.Entry<String, Long>::getValue, Comparator.reverseOrder()) - 修正后的完整可运行代码如下:
public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String input = scanner.nextLine(); Arrays.stream(input.split(" ")) .map(word -> word.replaceAll("[^A-Za-z0-9]", "")) .map(String::toLowerCase) .filter(word -> !word.isEmpty()) // 过滤清洗后为空的无效词 .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) .entrySet() .stream() // 明确泛型后调用反转,不会触发编译错误 .sorted(Comparator.comparingLong((Map.Entry<String, Long> e) -> e.getValue()).reversed()) .limit(10) .sorted(Comparator.comparing(Map.Entry::getKey)) .forEach(e -> System.out.println(e.getKey())); }
新手常见认知澄清
- 不需要为了反转排序写复杂逻辑,Java Comparator本身已封装好正反排序的能力,只要把类型写明确,链式调用就不会出问题。
- 你代码里“取完Top10高频词后再按单词字典序排序”的逻辑是自洽的,不需要额外修改;如果不需要按字典序输出,删掉那行
.sorted(Comparator.comparing(Map.Entry::getKey))即可。 Map.Entry自带的comparingByValue()、comparingByKey()静态方法也可以直接使用,要实现高频排序的话可以直接写.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())),代码会更简洁。
内容的提问来源于stack exchange,提问作者Ebrin
相关产品推荐
相关产品推荐

