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

网友投稿 407 2022-12-14

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

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

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

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

如下代码

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 map = new HashMap();

map.put(str1,"value1");

map.put(str2,"value2");//会覆盖之前的值,map长度为1

/**

* map比较键是否相同时是根据hashCode()和equals()两个方法进行比较

* 先比较hashCode()是否相等,再比较equals()是否相等(实际上就是比较对象是否相等),如果都相等则认定是同一个键

*/

for(Map.Entry 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 map = new IdentityHashMap<>();

map.put(str1,"value1");

map.put(str2,"value2");

for(Map.Entry 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 map = new IdentityHashMap<>();

map.put(str1,"value1");

map.put(str2,"value2");

for(Map.Entry 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提供的Mhttp://ultiValueMap。

public static void main(String[] args) {

Map identity = new IdentityHashMap<>();

identity.put("A", "A");

identity.put("A", "B");

identity.put("A", "C");

Map identityString = new IdentityHashMap<>();

identityString.put(String.join("A", ""), "B");

identityString.put("A", "A");

identityString.put(new String("A"), "C");

MultiValueMap 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提供的Identihttp://tyHashMap其底层是根据Key的hash码的不同+transient Object[] table来实现的;

Spring提供的LinkedMultiValueMap其底层是使用LinkedHashMap来实现的;

LinkedHashMap的底层是使用transient Entry head和transient Entry tail来实现的;

Entry是LinkedHashMap的内部类,其定义方式为:

static class Entry extends HashMap.Node { Entry before; Entry after; }

总结

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

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java日常练习题,每天进步一点点(63)
下一篇:使用Filter拦截器如何实现请求跨域转发
相关文章

 发表评论

暂时没有评论,来抢沙发吧~