Map更新映射项技巧

Map中处理映射时的一个难点就是更新映射项,如果Map中没有指定key,就直接把value设为0,但是如果Map中如果有了指定key,就要把当前key关联value更新,并放回更新后的值。下面是一个例子:

键盘录入字符串,统计每个字符出现的次数

public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("请录入一个字符串:");
		String line = sc.nextLine();
		char[] chs = line.toCharArray();// 字符串转字符数组
		Map<Character, Integer> map = new HashMap<>();// 字符数组中数据存入HashMap
		for (char c : chs) {// 对每一个字符进行判断
			if (!map.containsKey(c)) {// map中没有c键,说明第一次统计字符,设置key的value为1
				map.put(c, 1);
			} else {// map中有c键,说明不是第一次统计字符,把当前key的value设置为+1
				map.put(c, map.get(c) + 1);
			}
		}
		StringBuilder sb = new StringBuilder();
		Set<Entry<Character, Integer>> entrySet = map.entrySet();// 用entrySet()得到Set对象
		for (Entry<Character, Integer> entry : entrySet) {// 对每一个Set对象进行拼接
			char ch = entry.getKey();
			int num = entry.getValue();
			sb.append(ch).append("出现了").append(num).append("次,");
		}
		System.out.println(sb.substring(0, sb.length() - 1));// 截取子串,清除最后一个逗号
	}

在对char[ ] 数组遍历的foreach中,使用了if - else结构,其实还可以写成三元表达式:

for (char c : chs) {// 对每一个字符进行判断
			/*if (!map.containsKey(c)) {// map中没有c键,说明第一次统计字符,设置key的value为1
				map.put(c, 1);
			} else {// map中有c键,说明不是第一次统计字符,把当前key的value设置为+1
				map.put(c, map.get(c) + 1);
			}*/
			map.put(c, map.containsKey(c) ? map.get(c) + 1 : 1);
		}

但是这个三元表达式其实没有针对刚刚的难点做出相应的优化,第一次出现key时依然取定值,重复出现key时依然要+ 1。那么有没有更优雅的代码呢?Java8的merge方法就是针对这种情况而设计的:

for (char c : chs) {// 对每一个字符进行判断
			/*if (!map.containsKey(c)) {// map中没有c键,说明第一次统计字符,设置key的value为1
				map.put(c, 1);
			} else {// map中有c键,说明不是第一次统计字符,把当前key的value设置为+1
				map.put(c, map.get(c) + 1);
			}*/
			// map.put(c, map.containsKey(c) ? map.get(c) + 1 : 1);
			map.merge(c, 1, Integer::sum);
		}

在这里,我们进一步省略了代码。Java8的API是这样介绍merge( )的:

      • default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)
        如果指定的键尚未与值相关联或与null相关联,则将其与给定的非空值相关联。 否则,将关联值替换为给定重映射函数的结果,如果结果为null 。 当组合键的多个映射值时,该方法可能是有用的。 例如,要创建或附加String msg到值映射:
           map.merge(key, msg, String::concat)  

        如果函数返回null ,则删除映射。 如果函数本身引发(未检查)异常,则异常被重新引导,并且当前映射保持不变。

对于上面例子来说,这个方法其实是说:如果键原先不存在,

counts . merge ( c , 1 , Integer : : sum ) ;


将把 c 与 1 关联 , 否则使用 Integer :: sum 函数组合原值和 1 ( 也就是将原值与 1 求和 ) 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值