当前位置:LBNB > 实用知识 > java(map中相同的key保存多个value值方式)

java(map中相同的key保存多个value值方式)

java,map中相同的key保存多个value值方式,萝卜牛逼网带你了解更多相关信息。

目录
  • map中相同的key保存多个value值
    • 如下代码
  • Map中相同的键Key不同的值Value实现原理
    • 实现原理
    • 总结

map中相同的key保存多个value值

在java中,Map集合中只能保存一个相同的key,如果再添加相同的key,则之后添加的key的值会覆盖之前key对应的值,Map中一个key只存在唯一的值。

java(map中相同的key保存多个value值方式)

如下代码

package test; import org.junit.Test; import java.util.HashMap;import java.util.IdentityHashMap;import java.util.Map; import static java.util.Objects.hash; public class HashMapTest {     @Test    public void test0() {        String str1 = new String(\"key\");        String str2 = new String(\"key\");        System.out.println(str1 == str2);         Map<String,String> map = new HashMap<String,String>();        map.put(str1,\"value1\");        map.put(str2,\"value2\");//会覆盖之前的值,map长度为1        /**         * map比较键是否相同时是根据hashCode()和equals()两个方法进行比较         * 先比较hashCode()是否相等,再比较equals()是否相等(实际上就是比较对象是否相等),如果都相等则认定是同一个键         */         for(Map.Entry<String,String> entry: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接口,比较键(和值)时使用引用相等性代替对象相等性,     * 也就是说做key(value)比较的时候只比较两个key是否引用同一个对象)     */    @Test    public void test1(){        String str1 = \"key\";        String str2 = \"key\";        System.out.println(str1 == str2);        Map<String,String> map = new IdentityHashMap<>();        map.put(str1,\"value1\");        map.put(str2,\"value2\");        for(Map.Entry<String,String> entry:map.entrySet()){  System.out.println(entry.getKey()+\"  \"+entry.getValue());        }        System.out.println(\"containsKey---->\"+map.get(\"key\"));        System.out.println(\"value---->\"+map.get(\"key\"));    } 控制台输出如下   /**     * test1中的IdentityHashMap中的key为“key”还是只保存了一个值,以为“key”在内存中只存在一个对象,     * 而str1与str2对对\"key\"字符串的引用是相等的,所以添加的时候就发生了覆盖     */     @Test    public void test2(){        String str1 = new String(\"key\");        String str2 = new String(\"key\");        System.out.println(str1 == str2);        Map<String, String> map = new IdentityHashMap<>();        map.put(str1,\"value1\");        map.put(str2,\"value2\");        for(Map.Entry<String,String> entry:map.entrySet()){  System.out.println(entry.getKey()+\"  \"+entry.getValue());        }        System.out.println(\"\\\"key\\\" containKey--->\"+map.containsKey(\"key\"));        System.out.println(\"str1 containKey--->\"+map.containsKey(str1));        System.out.println(\"str2 containKey--->\"+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对象,他们的哈希值是不同的,所以在identityHashMap中可以的比较     * 中会认为不同的key,所以会存在相同的“key”值对应不同的value值     */      /**     * 既然提到了map的key的比较,再说一下map中实现自定义类做key值时应该注意的一些细节,     * 在HashMap中对于key的比较时通过两步完成的     *  第一步:计算对象的hash Code的值,比较是否相等     *  第二步: 检查对应的hash code对应位置的对象是否相等     *  在第一步中会调用到对象中的hashCode()方法,第二步中会调用的对象中的equals()方法     *     *  所以想要实现自定义对象作为Map的key值,保证key值的唯一性,需要在子定义对象中重写以上两个方法,如以下对象:     */    private class CustomObject{        private String value;         public CustomObject(String value){  this.value = value;        }         public String getValue() {  return value;        }         public void setValue(String value) {  this.value = value;        }         /**         * 省略自定义的一些属性方法         * ......         */@Override        public int hashCode() {  if(value !=null){      return super.hashCode()+hash(value);  }else{      return super.hashCode();  }        }         @Override        public boolean equals(Object obj) {  if(this == obj){      return true;  }  if(obj == null || getClass() != obj.getClass()){      return false;  }  CustomObject object = (CustomObject) obj;  if(this.value != null && this.value.equals(object.getValue())){      return true;  }  if(this.value == null && object.value == null){      return true;  }  return false;        }    } }

Map中相同的键Key不同的值Value实现原理

Map中相同的键Key对应不同的值Value通常出现在树形结构的数据处理中,通常的实现方法有JDK提供的IdentityHashMap和Spring提供的MultiValueMap。

public static void main(String[] args) {Map<String, Object> identity = new IdentityHashMap<>();identity.put(\"A\", \"A\");identity.put(\"A\", \"B\");identity.put(\"A\", \"C\");Map<String, Object> identityString = new IdentityHashMap<>();identityString.put(String.join(\"A\", \"\"), \"B\");identityString.put(\"A\", \"A\");identityString.put(new String(\"A\"), \"C\");MultiValueMap<String, Object> linked = new LinkedMultiValueMap<>();linked.add(\"A\", \"A\");linked.add(\"A\", \"B\");linked.add(\"A\", \"C\");for (String key : identity.keySet()) {System.out.println(\"identity:\" + identity.get(key));}for (String key : identityString.keySet()) {System.out.println(\"identity string:\" + identityString.get(key));}for (String key : linked.keySet()) {System.out.println(\"linked:\" + linked.get(key));}}

实现原理

  • JDK提供的IdentityHashMap其底层是根据Key的hash码的不同+transient Object[] table来实现的;
  • Spring提供的LinkedMultiValueMap其底层是使用LinkedHashMap来实现的;
  • LinkedHashMap的底层是使用transient Entry<K, V> head和transient Entry<K, V> tail来实现的;
  • Entry是LinkedHashMap的内部类,其定义方式为:

static class Entry<K, V> extends HashMap.Node<K, V> { Entry<K, V> before; Entry<K, V> after; }

总结

IdentityHashMap和LinkedMultiValueMap的实现归根结底就是数组和链表的使用。

java(map中相同的key保存多个value值方式)

以上为个人经验,希望能给大家一个参考,也希望大家多多支持趣讯吧。