Java代码在Eclipse正常运行但在线IDE报空指针异常求排查
解决HashMap求最大值键时的NullPointerException问题
看起来你的代码在本地Eclipse能正常运行,但在线IDE直接炸了——根源是Collections.max(map.values())抛出了空指针异常,这是因为你的HashMap里混入了null值,而Collections.max在比较元素时遇到null就会触发这个错误。
为什么会出现null值?
你踩了一个Scanner使用的常见坑:同时用两个Scanner实例读取同一个System.in输入流。
当你用Scanner s读取学生姓名后,Scanner e再去读取分数时,输入流的指针已经被s移动过了,这会导致e.hasNext()可能返回false,进而让mark[i]保持默认的null值,然后你直接把这个null塞进了HashMap。一旦map的values集合里有null,Collections.max就会报错——它会尝试用compareTo比较元素,而null不能和Double做比较。
另外还有个隐藏小问题:你用==比较Double值,这对于包装类型来说很危险——==比较的是对象引用,不是实际数值,比如Double.valueOf(100.0)和new Double(100.0)用==比较会返回false。
修复方案
这里给你调整后的代码,解决了所有问题:
import java.util.*; import java.util.Map.Entry; class Main{ public static void main(String args[])throws Exception{ Scanner s = new Scanner(System.in); HashMap<String,Double> hm=new HashMap<String,Double>(); System.out.println("Enter the number of students "); int n=s.nextInt(); s.nextLine(); // 处理nextInt后遗留的换行符 for(int i=0;i<n;i++) { System.out.println("Enter the details of the student "+(i+1)); String name = s.nextLine(); // 只用一个Scanner读取所有输入,避免流冲突 double mark = s.nextDouble(); s.nextLine(); // 处理nextDouble后的换行符,保证下一次读取姓名正常 hm.put(name, mark); } String maxKey = getMaxEntry(hm).getKey(); System.out.println(maxKey); } public static Entry<String, Double> getMaxEntry(Map<String, Double> map){ Entry<String, Double> maxEntry = null; // 先判断map是否为空,避免空指针 if(map.isEmpty()){ return null; } Double max = Collections.max(map.values()); for(Entry<String, Double> entry : map.entrySet()) { Double value = entry.getValue(); // 用equals比较Double数值,替换==的引用比较 if(value != null && max.equals(value)) { maxEntry = entry; break; // 取第一个遇到的最大值对应的键,如需全部可移除break } } return maxEntry; } }
关键修复点说明
- 移除多余的Scanner:只用一个
Scanner s处理所有输入,彻底避免输入流的竞争问题,保证分数能被正确读取,不会出现null值。 - 处理换行符残留:每次用
nextInt()或nextDouble()后,都调用s.nextLine()吃掉换行符,防止下一次nextLine()读取到空字符串。 - 正确比较Double值:用
max.equals(value)替代==,确保比较的是实际数值而非对象引用。 - 空map防御:在
getMaxEntry开头判断map是否为空,避免极端情况下再次触发空指针。
内容的提问来源于stack exchange,提问作者Siddarth Crm




