目录map中同一个key保存多个值下面的代码展示了Map中同一个key但是不同值的实现原理实现原理总结Map中同一个key保存多个值在Java中,Map集合中只能保存一个相同的key。如果添加了相同的key,后面添加的key的值会覆盖前面key对应的值。Map中的键只有一个唯一值。下面代码封装test;importorg.junit.Test;importjava.util.HashMap;importjava.util.IdentityHashMap;importjava.util.Map;importstaticjava.util.Objects.hash;publicclassHashMapTest{@Testpublicvoidtest0(){Stringstr1=newString("key");Stringstr2=newString("key");System.out.println(str1==str2);Mapmap=newHashMap();map.put(str1,"value1");map.put(str2,"value2");//之前的value会被覆盖,map的长度为1/***map比较key是否相同同时根据比较hashCode()和equals()这两个方法*先比较hashCode()是否相等,再比较equals()是否相等(实际上是比较对象是否相等),如果都相等,则认为是相同的键*/for(Map.Entryentry:map.entrySet()){System.out.println(entry.getKey()+""+entry.getValue());}System.out.println("-------->"+map.get("key"));}控制台输出如下:/***以上代码说明普通map集合中同一个key只能保存一个value*但是有一种特殊的map--->IdentityHashMap可以实现一个key保存多个value*注意:这个类不是一般的Map实现!该类实现Map接口时,违反了Map的正则约定。Map的正则约定强制在比较对象中使用equals()方法,但是这种设计只用于需要引用相等语义的情况*(IdentityhashMap类使用哈希表实现Map接口,比较键(和值)时使用引用相等而不是对象相等,*也就是说在做键(值)比较时只比较两个键是否引用同一个对象)*/@Testpublicvoidtest1(){Stringstr1="钥匙";字符串str2="键";System.out.println(str1==str2);Mapmap=newIdentityHashMap<>();地图。放(str1,“value1”);map.put(str2,"value2");for(Map.Entryentry:map.entrySet()){System.out.println(entry.getKey()+""+entry.getValue());}System.out.println("containsKey---->"+map.get("key"));System.out.println("值---->"+map.get("key"));}控制台输出如下/***test1中IdentityHashMap中的key为“key”或者只保存了一个value,认为“key”在内存中只有一个对象,*str1和str2等于引用“key”字符串,所以在添加*/@Testpublicvoidtest2(){Stringstr1=newString("key");Stringstr2=newString("key");System.out.println(str1==str2);Mapmap=newIdentityHashMap<>();map.put(str1,"value1");map.put(str2,"value2");for(Map.Entryentry:map.entrySet()){System.out.println(entry.getKey()+""+entry.getValue());}System.out.println("\"key\"containKey--->"+map.containsKey("key"));System.out.println("str1containKey--->"+map.containsKey(str1));System.out.println("str2containKey--->"+map.containsKey(str2));System.out.println("value--->"+map.get("key"));System.out.println("value--->"+map.get(str1));System.out.println("value--->"+map.get(str2));}控制站内输出如下:/***test2中,str1和str2指向内存中不同的String对象,它们的hash值不同,所以identityHashMap中可能的比较会考虑不同的key,所以它们会存在相同的“键”值对应不同的值*//***说了map的key的比较,下面说说自定义类在map中的实现作为key值的注意事项感兴趣的一些细节,*在HashMap中,key的比较是分两步完成的。*第一步:计算对象的hashCode值,比较是否相等。*第二步:检查对应hashcode对应的对象是否为Equality*第一步会调用对象中的hashCode()方法,第二步会调用对象中的equals()方法**所以想实现一个自定义对象作为Map的键值,保证键值唯一性,需要在子定义对象中重写上面两个方法,比如下面的对象:*/privateclassCustomObject{私有字符串值;publicCustomObject(Stringvalue){this.value=value;}publicStringgetValue(){返回值;}publicvoidsetValue(Stringvalue){this.value=value;}/***省略一些自定义属性方法*......*/@OverridepublicinthashCode(){if(value!=null){returnsuper.hashCode()+hash(value);}else{返回super.hashCode();}}@Overridepublicbooleanequals(Objectobj){if(this==obj){返回true;}如果(obj==null||getClass()!=obj.getClass()){返回false;}CustomObject对象=(CustomObject)obj;if(this.value!=null&&this.value.equals(object.getValue())){返回真;}if(this.value==null&&object.value==null){返回真;}返回假;键Key对应不同的值。值通常出现在树形结构的数据处理中。通常的实现方式有JDK提供的IdentityHashMap和Spring提供的MultiValueMap。publicstaticvoidmain(String[]args){Mapidentity=newIdentityHashMap<>();identity.put("A","A");identity.put("A","B");identity.put("A","C");MapidentityString=newIdentityHashMap<>();identityString.put(String.join("A",""),"B");identityString.put("A","A");identityString.put(newString("A"),"C");MultiValueMaplinked=newLinkedMultiValueMap<>();linked.add("A","A");linked.add("A","B");linked.add("A","C");for(Stringkey:identity.keySet()){System.out.println("identity:"+identity.get(key));}for(Stringkey:identityString.keySet()){System.out.println("identitystring:"+identityString.get(key));}for(Stringkey:linked.keySet()){System.out.println("linked:"+linked.get(key));}}实践原理JDK提供的IdentityHashMap其底层是根据Key的hash码的不同+transientObject[]table来实现Spring提供的LinkedMultiValueMap底层是使用LinkedHashMap实现的;LinkedHashMap底层使用transientEntryhead和transientEntrytail实现;Entry是LinkedHashMap的内部类,它的定义方法是:staticclassEntryextendsHashMap.Node{Entrybefore;条目之后;}总结IdentityHashMap和LinkedMultiValueMap的实现归根结底是数组和链表上面的使用是个人经验,希望给大家参考