为何Integer二维数组元素默认非null?空指针问题求助
问题根源与解决方案
核心问题
你对Java二维数组的初始化逻辑理解有误:
- 执行
Integer[][] bucket = new Integer[nums.length+1][1];时,Java会为外层数组的每一个索引位置自动创建一个长度为1的Integer子数组,这些子数组内的元素默认是null(因为Integer是引用类型)。 - 你原本以为未被赋值的
bucket[i]是null,但实际上它们都是已初始化的子数组,只是子数组里的元素没被赋值。这就导致遍历判断bucket[i] != null时,那些从未被freqMap处理过的索引也会进入分支,而它们的bucket[i][0]是null,赋值给int类型的数组元素时触发NullPointerException。 - 额外问题:你的
if (bucket[frequency] == null)判断永远不会成立,因为所有bucket[i]都已被初始化,这个分支完全无效。
修复方案
方案1:修正数组初始化方式
只创建外层数组,不自动初始化内层子数组,让未被处理的bucket[i]保持null,符合你的预期逻辑:
public int[] topKFrequent(int[] nums, int k) { Map<Integer, Integer> freqMap = new HashMap<>(); for(int num : nums) freqMap.put(num, freqMap.getOrDefault(num, 0)+1); // 仅初始化外层数组,内层默认是null Integer[][] bucket = new Integer[nums.length+1][]; for(int key : freqMap.keySet()) { int frequency = freqMap.get(key); if (bucket[frequency] == null) { bucket[frequency] = new Integer[1]; } bucket[frequency][0] = key; } int[] res = new int[k]; int resIdx = 0; for(int i = bucket.length-1; i>=0; i--) { if(bucket[i] != null) { System.out.println(i); System.out.println(bucket[i][0]); res[resIdx++] = bucket[i][0]; if(resIdx == k) return res; } } return res; }
方案2:完善遍历判断逻辑
保留原数组初始化方式,但在遍历的时候同时检查子数组元素是否为null:
// ... 前面代码不变 for(int i = bucket.length-1; i>=0; i--) { if(bucket[i] != null && bucket[i][0] != null) { System.out.println(i); System.out.println(bucket[i][0]); res[resIdx++] = bucket[i][0]; if(resIdx == k) return res; } } // ...
额外优化:处理同频率的多个元素
当前代码存在逻辑缺陷:如果有多个元素的频率相同,后面的元素会覆盖前面的元素(因为每个bucket[frequency]只有一个存储位置)。建议改用List<Integer>[]来存储同频率的所有元素:
public int[] topKFrequent(int[] nums, int k) { Map<Integer, Integer> freqMap = new HashMap<>(); for(int num : nums) freqMap.put(num, freqMap.getOrDefault(num, 0)+1); List<Integer>[] bucket = new List[nums.length+1]; // 初始化每个频率对应的空列表 for(int i = 0; i < bucket.length; i++) { bucket[i] = new ArrayList<>(); } // 将元素按频率分组 for(Map.Entry<Integer, Integer> entry : freqMap.entrySet()) { bucket[entry.getValue()].add(entry.getKey()); } int[] res = new int[k]; int resIdx = 0; // 从高频率到低频率遍历,收集元素 for(int i = bucket.length-1; i>=0 && resIdx < k; i--) { for(int num : bucket[i]) { res[resIdx++] = num; if(resIdx == k) break; } } return res; }
内容的提问来源于stack exchange,提问作者Sophy Tao
相关产品推荐
相关产品推荐

