关于java里Map的value 相同的个数的问题?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于java里Map的value 相同的个数的问题?相关的知识,希望对你有一定的参考价值。

比如,有一个Map {t1=a,t2=b,t3=c,t4=a,t5=c,t6=a,t7=b,t8=b}
求Map中a,b,c的个数.

求高手帮助。
value是不确定的,都是从库里读出来的。

看例子
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class A

/**
* @param args
*/
public static void main(String[] args)

Map<String, String> map= new HashMap<String, String>();

map.put("1", "a");
map.put("2", "b");
map.put("3", "a");
map.put("4", "c");
map.put("5", "a");

Iterator<String> ite = map.values().iterator();

Map<String, Integer> countMap =new HashMap<String, Integer>();

while(ite.hasNext())
String item = ite.next();

if(countMap.containsKey(item))
countMap.put(item, Integer.valueOf(countMap.get(item).intValue() + 1));
else
countMap.put(item, new Integer(1));



//print the count
for (Iterator iter = countMap.keySet().iterator(); iter.hasNext();)
String key = (String) iter.next();
System.out.println(key + " apperas " + countMap.get(key) + " times");




参考技术A 循环一次Map集合时,顺便记录一下每一个value出现的个数不就可以了。追问

我举的例子是很简单,实际情况是,value值是不确定的。

追答

value值不确定的时候,也是可以的,你用一个集合类,将每次得到的value都存起来,下次循环取出来的时候,看一下,在原来存的value中有没有,有就在其数量上加1,没有就另外再加一个value咯,这样不就Ok了。

既然是从库里读出来的,为什么不在SQL语句的时候,就直接group by 呢, >???????

参考技术B 貌似你只能遍历取值然后再统计了

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<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的value 相同的个数的问题?的主要内容,如果未能解决你的问题,请参考以下文章

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

java map的key可以重复吗

java for循环 怎样把一个list里相同的数据放到一起

关于Java的Map

java中Map可以有相同的value吗

java中Map可以有相同的value吗