为何定义PriorityQueue比较器的Lambda表达式无法正常工作?
问题:创建基于List第一个元素的最小堆编译错误
想要创建一个存储整数对(以List<Integer>表示)的最小堆,基于元素对的第一个整数进行比较,初始代码如下:
PriorityQueue<List<Integer>> heap = new PriorityQueue((a, b) -> a.get(0) - b.get(0));
编译时出现以下错误:
ERROR! javac /tmp/1YraTeGijp/HelloWorld.java /tmp/1YraTeGijp/HelloWorld.java:7: error: cannot find symbol PriorityQueue<List<Integer>> heap = new PriorityQueue((a, b) -> a.get(0) - b.get(0)); ^ symbol: method get(int) location: variable a of type Object /tmp/1YraTeGijp/HelloWorld.java:7: error: cannot find symbol PriorityQueue<List<Integer>> heap = new PriorityQueue((a, b) -> a.get(0) - b.get(0)); ^ symbol: method get(int) location: variable b of type Object Note: /tmp/1YraTeGijp/HelloWorld.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.
修复方案
方法1:明确指定泛型与Lambda参数类型
创建PriorityQueue时必须明确泛型参数List<Integer>,同时给Lambda表达式的参数指定类型,让编译器识别get()方法:
PriorityQueue<List<Integer>> heap = new PriorityQueue<List<Integer>>( (List<Integer> a, List<Integer> b) -> a.get(0) - b.get(0) );
方法2:用菱形运算符简化泛型声明(Java 7+)
借助Java 7的菱形运算符<>,编译器会根据左侧声明推断泛型类型,只需给Lambda参数指定类型即可:
PriorityQueue<List<Integer>> heap = new PriorityQueue<>( (List<Integer> a, List<Integer> b) -> a.get(0) - b.get(0) );
方法3:用Comparator静态方法简化代码(Java 8+)
使用Comparator.comparingInt()直接提取第一个元素作为比较依据,代码更简洁且类型安全:
PriorityQueue<List<Integer>> heap = new PriorityQueue<>( Comparator.comparingInt(list -> list.get(0)) );
错误原因
原代码中new PriorityQueue()未指定泛型类型,编译器将Lambda参数a、b默认视为Object类型,而Object没有get()方法,因此报错。即便单独给Lambda参数指定类型,若队列未明确泛型,仍会出现类型不匹配问题,必须同时明确队列的泛型类型。
内容的提问来源于stack exchange,提问作者Eyoel Gebre
相关产品推荐
相关产品推荐

