Scanner的nextInt()与nextLine()搭配遇到的坑

前言

笔者前几天在刷一道牛客网上的华为校招的练习题,被这道练习题(和华为)坑了一把,这几天越想越郁闷,所以记下这次遇到的bug。

题外话

当时的题目如下,感兴趣的同学可以瞧瞧,我写的参考代码会放到最后。

数据表记录包含表索引和数值(int范围的整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照key值升序进行输出。

输入描述:
先输入键值对的个数
然后输入成对的index和value值,以空格隔开

输出描述:
输出合并后的键值对(多行)

入正题

当时我想的是先用nextInt()读取到第一个数,读到该数后建立一个for循环,然后再使用nextLine()循环读入下一行的数值,一开始的代码大概如下。
在这里插入图片描述
毫无疑问,输入案例后就开始报错了。
在这里插入图片描述

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:592)
	at java.lang.Integer.parseInt(Integer.java:615)
	at com.zp.huaweinowcoder.main8.Main.main(Main.java:17)

说我输入的是空字符串。后来几经查找才查出缘由。

错误原因

第一得知道在控制台输入的数据字符会先进缓冲区中等待Scanner的扫描,除非遇到空格或者回车之类的空白符才会停止扫描。
nextInt() 的原理是扫描到空白符时会把空白符前面的数据读取走,最后再缓冲区遗留空白符——"\r"。
nextLine() 的原理是把连同空白符在内的一行一同读取。
所以这里就不难理解为什么读完nextInt()后nextLine()再读是一串空字符,另外next()nextDouble()nextFloat() 这些与nextInt()同理,所以使用时都得注意空格符。
解决办法 自然就是执行nextInt()后再加个nextLine()把空格符读走。
在这里插入图片描述

附上算法代码

import java.util.*;

/**
 * @author ZP
 * @date 2020/1/12.
 */
public class Main {
    public static void main(String[] args) {
        Scanner sr = new Scanner(System.in);
        while (sr.hasNext()){
            int n = sr.nextInt();
            sr.nextLine();
            Map map = new HashMap();
            for (int i = 0; i < n; i++) {
                String[] strAnrry = sr.nextLine().split(" ");
                if (map.containsKey(Integer.parseInt(strAnrry[0]))) {
                    int oldn = (int) map.get(Integer.parseInt(strAnrry[0]));
                    int newn = oldn + Integer.parseInt(strAnrry[1]);
                    map.replace(Integer.parseInt(strAnrry[0]),newn);
                }else {
                    map.put(Integer.parseInt(strAnrry[0]),Integer.parseInt(strAnrry[1]));
                }
            }

            Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();    //获取map集合的所有"映射"的Set集合,这里规范每个映射的类型为Map.Entry<K, V>(于Set集合中无序存放)
            List<Map.Entry<Integer, Integer>> list = new ArrayList<Map.Entry<Integer, Integer>>(entrySet);    //新建List集合获取Set集合的所有元素("映射"对象)(顺序与Set集合一样)
            /**
             * 接下来的排序是list的专长了
             * 通过“比较器(Comparator)”,对list进行排序
             */
            Collections.sort(list, new Comparator<Map.Entry<Integer, Integer>>() {

                @Override
                public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                    return o1.getKey().toString().compareTo(o2.getKey().toString());
                }
            });

            Iterator<Map.Entry<Integer, Integer>> iter = list.iterator();    //获取List集合的迭代器,Map.Entry<K, V>为迭代元素的类型
            while(iter.hasNext()){
                Map.Entry<Integer, Integer> item = iter.next();
                Integer key = item.getKey();
                Integer value = item.getValue();
                System.out.println(key + " " + value);
            }
        }
    }
}

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值