You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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集合里有nullCollections.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;
    }
}

关键修复点说明

  1. 移除多余的Scanner:只用一个Scanner s处理所有输入,彻底避免输入流的竞争问题,保证分数能被正确读取,不会出现null值。
  2. 处理换行符残留:每次用nextInt()nextDouble()后,都调用s.nextLine()吃掉换行符,防止下一次nextLine()读取到空字符串。
  3. 正确比较Double值:用max.equals(value)替代==,确保比较的是实际数值而非对象引用。
  4. 空map防御:在getMaxEntry开头判断map是否为空,避免极端情况下再次触发空指针。

内容的提问来源于stack exchange,提问作者Siddarth Crm

火山引擎 最新活动