不同spring-framework版本中的LinkedCaseInsensitiveMap区别

1 篇文章 0 订阅
1 篇文章 0 订阅

在用eclipse维护一个老项目的过程中,debug代码的时候发现一个LinkedCaseInsensitiveMap类型的map,get的时候不区分key值的大小写,但是在put的时候会区分大小写。如:

LinkedCaseInsensitiveMap<String> map = new LinkedCaseInsensitiveMap<String>();
//在eclipse中debug时,在Variables窗口点击该map变量会发现显示为{Aa:1,aa:2}
map.put("Aa","1");
map.put("aa","2");
//get时均会显示2
map.get("Aa");//显示:2
map.get("aa");//显示:2

后查看源码才得知,由于老项目中引用的是org.springframework.core-3.0.2.RELEASE.jar

在该版本jar包中LinkedCaseInsensitiveMap.java的属性及其get和put方法内容如下:


package org.springframework.util;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;


public class LinkedCaseInsensitiveMap<V> extends LinkedHashMap<String, V> {

	private final Map<String, String> caseInsensitiveKeys;

	private final Locale locale;

    //调用put方法时,
	@Override
	public V put(String key, V value) {
        //1.将传入的key,用convertKey(key)方法将字母转换成小写返回lowerCaseKey
        //(为便于理解,转换后的key命名为lowerCaseKey),
        //再将<lowerCaseKey, key>该键值对存入caseInsensitiveKeys
		this.caseInsensitiveKeys.put(convertKey(key), key);

        //2.将<传入的key,传入的value>存入LinkedHashMap中(该类继承了LinkedHashMap)
		return super.put(key, value);
	}

    //调用get方法时,
	@Override
	public V get(Object key) {
		if (key instanceof String) {
            //1.convertKey((String) key):将传入的key中字母转换成小写lowerCaseKey
            //2.this.caseInsensitiveKeys.get(lowerCaseKey):
            //获取 lowerCaseKey在caseInsensitiveKeys对应的值key(该key其实就是put时传入的原key)                        
            //3.super.get(key):获取key在LinkedHashMap对应的value(该value才是put时传入的value)
			return super.get(this.caseInsensitiveKeys.get(convertKey((String) key)));
		}
		else {
			return null;
		}
	}

    //将key中的字母根据locale的规则转换成小写
	protected String convertKey(String key) {
		return key.toLowerCase(this.locale);
	}

}

(注:v3.0.2.RELEASE 中完整的LinkedCaseInsensitiveMap源代码,通过以下地址可查看spring-framework/LinkedCaseInsensitiveMap.java at v3.0.2.RELEASE · spring-projects/spring-framework · GitHub)

看了以上源代码再分析一下,我开头举得例子:

LinkedCaseInsensitiveMap<String> map = new LinkedCaseInsensitiveMap<String>();
//map.put("Aa","1")执行完后,map中属性caseInsensitiveKeys变为:{"aa":"Aa"},其父类LinkedHashMap变为:{"Aa":"1"}
map.put("Aa","1");
//map.put("aa","2")执行完后,map中属性caseInsensitiveKeys变为:{"aa":"aa"}(原来的值"Aa"被覆盖),其父类LinkedHashMap变为:{"Aa":"1","aa":"2"}
map.put("aa","2");

//map.get("Aa")会先caseInsensitiveKeys.get("aa")得到aa,再根据aa获取LinkedHashMap的值,即LinkedHashMap.get("aa")得到值2.
//map.get("aa")也是相同过程,因为根据源代码convertKey("Aa")和convertKey("aa")得到的值是一致的
map.get("Aa");//显示:2
map.get("aa");//显示:2

 综上,LinkedCaseInsensitiveMap类继承了LinkedHashMap,又定义了Map<String, String> caseInsensitiveKeys属性。caseInsensitiveKeys用来存<字母转换成小写的key,key>,真正put时的<key,value>存在其父类LinkedHashMap中。由于字符串”aa“、”Aa“转换成小写都是"aa",所以在存入caseInsensitiveKeys时后一个put的会覆盖前一个的key(即对应上面例子<"aa","aa">会覆盖<"aa","Aa">),而由于存入LinkedHashMap时,"aa"、”Aa“不同,所以都会被存入(先put的一个所对应的value,通过map.get不管参数key大写还是小写永远获取不到,虽然在LinkedHashMap中存在

补充:在github上springframework.core-3.1.3.RELEASE版本中,LinkedCaseInsensitiveMap源代码put函数中,若put时key转换后的小写相同,caseInsensitiveKeys后put的覆盖前put的key,同时会移除LinkedHashMap中前put的key对应的value

    @Override
	public V put(String key, V value) {
		String oldKey = this.caseInsensitiveKeys.put(convertKey(key), key);
		if (oldKey != null && !oldKey.equals(key)) {
			super.remove(oldKey);
		}
		return super.put(key, value);
	}

(注:v3.1.3.RELEASE中完整的LinkedCaseInsensitiveMap源代码,通过以下地址可查看https://github.com/spring-projects/spring-framework/blob/v3.1.3.RELEASE/org.springframework.core/src/main/java/org/springframework/util/LinkedCaseInsensitiveMap.java)

如有错误,望指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值