精华内容
下载资源
问答
  • Java Map集合

    千次阅读 2019-02-07 10:00:39
    Map集合用于保存映射关系的数据,Map集合中保存了两组值,一组是 key, 一组是 value。 Map的key不能重复。 key和value之间存在单向一对一的关系, 通过key,能找到唯一的,确定的value。 HashMap和Hashtable是Map...

    Map集合

    Map集合用于保存映射关系的数据,Map集合中保存了两组值,一组是 key, 一组是 value。
    Map的key不能重复。
    key和value之间存在单向一对一的关系, 通过key,能找到唯一的,确定的value。

    public interface Map<K,V> {
        // Query Operations
    }
    

    Map的key放在一起来看,组成了一个Set集合,value又类似于一个List集合。
    Map接口中定义了如下常用方法:

    • clear():删除Map中所有的 key-value对
    • containsKey():是否包含指定的key
    • containsValue(): 是否包含一个或多个value。
    • entrySet(): 返回包含的 key-value对组成的Set集合,每个集合元素都是Map.Entry对象, Entry是Map的内部类。
    • get():返回指定key对应的value。
    • isEmpty(): 是否为空
    • keySet(): 返回key组成的Set集合
    • put(): 添加一个key-value对,如果存在,覆盖以前的
    • putAll(): 指定Map中复制过来
    • remove():删除指定key,或 key-value。
    • size():返回个数
    • values():返回所有 value组成的 Collection。
      JAVA 8 新增方法:
    • compute(): 根据第二个参数重新计算,并设置value
    • computeIfAbsent(): 同上,value为 Null时计算
    • computeIfPresent(): 同上, value不为Null时计算
    • forEach(): 遍历Map
    • merge(): value为null时,用传入的value覆盖,不为null时,重新计算覆盖
    • putIfAbsent(): value为null时覆盖
    • replace():key不存在时,不添加
    • replaceAll(): 重新计算key-value, 覆盖value。

    Map中包含一个内部接口 Entry。
    封装了一个key-value对。包含下面方法。

    • getKey(): 返回key
    • getValue(): 返回value
    • setValue(): 重新设置value
            Map map = new HashMap();
            map.put("A", 100);
            map.put("B", 90);
            map.put("C", 110);
            System.out.println(map);
    
            //D 不存在,不会改变
            map.replace("D", 80);
            System.out.println(map);
    
            //重新计算A
            map.merge("A", 20, (oldVal, newVal) -> (Integer)oldVal  + (Integer) newVal);
            System.out.println(map);
    
            //遍历
            map.forEach((key, value) -> System.out.println("key : " + key + " , value:" + value));
    
            //D 不存在,不存在时计算
            map.computeIfAbsent("D", (key) -> ((String) key).length());
            System.out.println(map);
    
            //D存在了, 存在计算
            map.computeIfPresent("D", (key, value) -> ((String) key).length() * 10);
            System.out.println(map);
    //Output
    {A=100, B=90, C=110}
    {A=100, B=90, C=110}
    {A=120, B=90, C=110}
    key : A , value:120
    key : B , value:90
    key : C , value:110
    {A=120, B=90, C=110, D=1}
    {A=120, B=90, C=110, D=10}
    

    HashMap和Hashtable

    HashMap和Hashtable是Map接口的实现类。

    public class HashMap<K,V> extends AbstractMap<K,V>
        implements Map<K,V>, Cloneable, Serializable {
    }
    
    public class Hashtable<K,V>
        extends Dictionary<K,V>
        implements Map<K,V>, Cloneable, java.io.Serializable {
    }
    

    Hashtable是古老的Map实现类,命名上都没有遵守JAVA命名规范,单词首字母大写。
    JAVA 8改进了HashMap的实现,使用HashMap存在key冲突时也有较好的性能。
    Hashtable 和 HashMap区别:
    Hashtable 是线程安全的, HashMap是线程不安全的。
    Hashtable 使用 null作为key和value, HashMap可以使用null作为key或value。 由于key不能重复, 最多只能有一个key为null。
    Hashtable 比较古老,性能较差, 不推荐使用,
    为了线程安全,可以使用 Collections 工具类。

            HashMap hashMap = new HashMap();
            hashMap.put("a", null);
            hashMap.put(null, null);
            hashMap.put(null, null);
            System.out.println(hashMap);
    //Output
    {null=null, a=null}
    

    HashMap 同 HashSet, 判断两个key相等标准也是: 两个key通过 equals方法返回true, hashCode()也相等。

    同HashSet, 可变对象最为HashMap的key, 程序如果修改了对象,程序无法准确的访问Map中的被修改的key。

    class AA{
        int count;
        public AA(int count){
            this.count = count;
        }
    
        @Override
        public boolean equals(Object obj) {
            if(obj == this)
                return true;
            if(obj != null && obj.getClass() == AA.class){
                AA a = (AA) obj;
                return a.count == this.count;
            }
            return false;
        }
    
        @Override
        public int hashCode() {
            return this.count;
        }
    }
    
    public class MapTest {
        public static void main(String[] args){
            HashMap hashMap = new HashMap();
            hashMap.put(new AA(100), "A");
            hashMap.put(new AA(200), "B");
            Iterator iterator = hashMap.keySet().iterator();
            AA aa = (AA) iterator.next();
            aa.count = 200;
            System.out.println(hashMap);
            //只能删除没有被修改过key的
            hashMap.remove(new AA(200));
            System.out.println(hashMap);
    
            //无法获取剩下的value
            System.out.println(hashMap.get(new AA(200)));
            System.out.println(hashMap.get(new AA(100)));
       }
    }
    //Output
    {testCode.AA@c8=A, testCode.AA@c8=B}
    {testCode.AA@c8=A}
    null
    null
    

    尽量不要使用可变对象作为 HashMap, Hashtable 的key, 如果使用,尽量不要修改作为key的可变对象。

    LinkedHashMap实现类

    LinkedHashMap 是 HashMap的子类。
    LinkedHashMap使用双向链表维护key-value的次序。使迭代顺序和插入顺序一致。

    public class LinkedHashMap<K,V>
        extends HashMap<K,V>
        implements Map<K,V>
    {
    
    }
    
            LinkedHashMap linkedHashMap = new LinkedHashMap();
            linkedHashMap.put("A", 100);
            linkedHashMap.put("B", 200);
            linkedHashMap.put("C", 300);
            linkedHashMap.forEach((key, value) -> System.out.println(key + " ---> " + value));
    //Output
    A ---> 100
    B ---> 200
    C ---> 300
    

    Properties

    Properties 是 Hashtable 的子类。

    public
    class Properties extends Hashtable<Object,Object> {
    
    }
    

    可以方便的处理属性文件。
    可以把属性文件,如 ini 中 属性名=属性值 加载到Map对象中。
    Properties 相当于 key, value都是 String类型的Map。
    主要有以下方法:

    • getProperty(): 获取属性值, 可以有 defaultValue。
    • setProperty(): 设置属性值
    • load():从属性文件中加载到 Properties里
    • store():输出到指定文件

    下面是使用:

            Properties properties = new Properties();
            properties.setProperty("name", "liu");
            properties.setProperty("age", "20");
            System.out.println(properties);
    
            properties.store(new FileOutputStream("p.ini"), "comment");
    
            Properties properties1 = new Properties();
            properties1.load(new FileInputStream("p.ini"));
            System.out.println(properties1);
    //Output
    {age=20, name=liu}
    {age=20, name=liu}
    

    根目录下生成 p.ini文件

    #comment
    #Wed Feb 06 18:24:46 CST 2019
    age=20
    name=liu
    

    TreeMap

    TreeMap 是 SortedMap接口的实现类。

    public class TreeMap<K,V>
        extends AbstractMap<K,V>
        implements NavigableMap<K,V>, Cloneable, java.io.Serializable
    {
    }
    
    public interface NavigableMap<K,V> extends SortedMap<K,V> {
    }
    
    public interface SortedMap<K,V> extends Map<K,V> {
    }
    

    TreeMap是根据 key来排序, 就是一个红黑树数据结构,每个key-value对是一个红黑树节点。保证所有的key-value对处于有序状态。

    同 TreeSet , 也有两种排序方法:
    自然排序
    定制排序。
    排序判断标准是根据 compareTo() 方法的返回值。
    主要方法包括: 取第一个, 最后一个, 前一个,后一个等 key-value对。 Map.Entry。

    WeakHashMap

    WeakHashMap 是 Map的实现类, 与HashMap基本相似.

    public class WeakHashMap<K,V>
        extends AbstractMap<K,V>
        implements Map<K,V> {
    }
    

    HashMap的key保留了对实际对象的强引用,只要该HashMap对象不被销毁,该HashMap的所有key所引用的对象就不会被垃圾收集。
    WeakHashMap 的key只保留了对实际对象的弱引用,该对象的key对所引用的对象没有被其他强引用对象所引用, 则key所引用的对象可能被垃圾回收,WeakHashMap也可能自动删除这些key所对应的key-value对。

            WeakHashMap weakHashMap = new WeakHashMap();
            //添加三个匿名字符串对象
            weakHashMap.put(new String("A"), 1);
            weakHashMap.put(new String("B"), 2);
            weakHashMap.put(new String("C"), 3);
            //添加key 系统缓存的字符串对象
            weakHashMap.put("java", 4);
    
            System.out.println(weakHashMap);
            System.gc();
            System.runFinalization();
            System.out.println(weakHashMap);
    //Output
    {java=4, C=3, B=2, A=1}
    {java=4}
    

    对于前三个匿名的字符串对象,WeakHashMap 保留了对他们的弱引用。垃圾回收时自动删除了这三个。
    对于第四个 key是一个字符串直接量,系统自动保留了强引用,所以垃圾回收时不会回收它。

    IdentityHashMap

    IdentityHashMap是Map的实现类, 与HashMap基本相似.
    他对处理两个 key相等时比较独特,当两个key严格相等时(key1 == key2).IdentityHashMap才认为两个key相等。
    对于普通HashMap, 只要 equals返回TRUE, 且 hashCode值相等即可。

    public class IdentityHashMap<K,V>
        extends AbstractMap<K,V>
        implements Map<K,V>, java.io.Serializable, Cloneable
    {
    }
    

    测试例子:

            IdentityHashMap identityHashMap = new IdentityHashMap();
            identityHashMap.put(new String("A"), 1);
            identityHashMap.put(new String("A"), 2);
            identityHashMap.put("B", 3);
            identityHashMap.put("B", 4);
            System.out.println(identityHashMap);
    //Output
    {A=2, A=1, B=4}
    

    前两个是新创建的字符串对象, == 为false,
    后两个是字符串直接量,JAVA使用常量池管理字符串直接量, == 为true

    EnumMap

    EnumMap是与枚举类一起使用的Map。
    key必须是单个枚举类的枚举值。

    public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
        implements java.io.Serializable, Cloneable
    {
    
    }
    
    • EnumMap内部以数组形式保存,这种实现非常紧凑,高效
    • EnumMap根据key在枚举类中的定义的顺序,维护key-value顺序。
    • 不允许 null 作为key
      下面示例:
    enum GenderEnum{
        MALE,FEMALE;
    }
    public class MapTest {
        public static void main(String[] args) throws  Exception{
            EnumMap enumMap = new EnumMap(GenderEnum.class);
            enumMap.put(GenderEnum.FEMALE, "女人");
            enumMap.put(GenderEnum.MALE, "男人");
            System.out.println(enumMap);
        }
    }
    //Output
    {MALE=男人, FEMALE=女人}
    

    FEMALE 先put, 但是输出还是按照枚举类中的定义顺序输出。

    Map性能分析

    HashMap 和 Hashtable 的实现机制几乎一样, Hashtable是一个古老的,线程安全的集合,因此 HashMap通常比Hashtable 性能好。
    TreeMap是红黑树管理key-value对,一直是排序状态,性能比HashMap要慢。
    LinkedHashMap比HashMap要慢, 需要链表来保持Map中的添加顺序。
    EnumMap性能最好,使用同一个枚举类的枚举值为key。

    性能选项

    HashMap, HashSet 等通过 hash 算法决定Map中 key的存储。
    hash 表里的存储元素的位置称为 桶,bucket。

    • 容量 capacity: hash表中桶的数量
    • 初始化容量 initial capacity: 创建 hash表时桶的数量
    • 尺寸 size: 当前 hash表中记录的数量
    • 负载因子(load factor):size/capacity. 0表示空hash表, 0.5表示半满的 hash表
      负载极限,表示hash表的最大填满程度,当负载因子达到负载极限时,进行 rehashing。 hash表会成倍的增加容量,桶的数量, 将原有的对象重新分配。
      负载极限默认值为 0.75。

    地址: https://blog.csdn.net/yonggang7/article/details/86768876

    展开全文
  • JAVA Map集合转String,String转Map集合 当前两个转换方法主要用作支付宝,微信支付额外参数转换 先看效果是不是诸君想要的 map转string的值 id=1&amp;amp;amp;amp;name=哆啦A梦丶幻想 string转...

    JAVA Map集合转String,String转Map集合##


    当前两个转换方法主要用作支付宝,微信支付额外参数转换

    先看效果是不是诸君想要的
    map转string的值
    id=1&name=哆啦A梦丶幻想

    string转map的值
    {name=哆啦A梦丶幻想, id=1}


    贴代码:

    	//这里是用单元测试测试的两个方法
        @Test
        public void filet(){
            Map<String,String> objectMap = new HashMap<>(3);
            objectMap.put("id","1");
            objectMap.put("name","哆啦A梦丶幻想");
            //map转string
            String passBackParams = StrUtils.getMapToString(objectMap);
            System.out.println(passBackParams);
            try {
                //string转map
               Map map =  StrUtils.getStringToMap(passBackParams);
                System.out.println(map);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    然后两个方法的主要代码:

    	//参数类型是Map<String,String> 因为支付只能用string的参数。如果诸君还需要修改的话,那也可以适当的做调整
    	/**
    	 *
    	 * map转str
    	 * @param map
    	 * @return
    	 */
    	public static String getMapToString(Map<String,String> map){
    		Set<String> keySet = map.keySet();
    		//将set集合转换为数组
    		String[] keyArray = keySet.toArray(new String[keySet.size()]);
    		//给数组排序(升序)
    		Arrays.sort(keyArray);
    		//因为String拼接效率会很低的,所以转用StringBuilder。博主会在这篇博文发后不久,会更新一篇String与StringBuilder开发时的抉择的博文。
    		StringBuilder sb = new StringBuilder();
    		for (int i = 0; i < keyArray.length; i++) {
    			// 参数值为空,则不参与签名 这个方法trim()是去空格
    			if (map.get(keyArray[i]).trim().length() > 0) {
    				sb.append(keyArray[i]).append("=").append(map.get(keyArray[i]).trim());
    			}
    			if(i != keyArray.length-1){
    				sb.append("&");
    			}
    		}
    		return sb.toString();
    	}
    
    	/**
    	 * 2018年10月24日更新
    	 * String转map
    	 * @param str
    	 * @return
    	 */
    	public static Map<String,String> getStringToMap(String str){
    		//感谢bojueyou指出的问题
    		//判断str是否有值
    		if(null == str || "".equals(str)){
    			return null;
    		}
    		//根据&截取
    		String[] strings = str.split("&");
    		//设置HashMap长度
    		int mapLength = strings.length;
    		//判断hashMap的长度是否是2的幂。
    		if((strings.length % 2) != 0){
    			mapLength = mapLength+1;
    		}
    
    		Map<String,String> map = new HashMap<>(mapLength);
    		//循环加入map集合
    		for (int i = 0; i < strings.length; i++) {
    			//截取一组字符串
    			String[] strArray = strings[i].split("=");
    			//strArray[0]为KEY  strArray[1]为值
    			map.put(strArray[0],strArray[1]);
    		}
    		return map;
    	}
    

    如有建议,欢迎指出。

    String,StringBuffer,StringBuilder有什么区别?项目中什么时候用?

    展开全文
  • java map集合如何遍历效率高java中Map遍历的方式 一、前言 1、在看 《阿里巴巴java开发手册》时候,有一条推荐的规约: 【推荐】使用entrySet遍历Map类集合KV,而不是keySet方式进行遍历。 说明:keySet其实是...

                                 java map集合如何遍历效率高 java中Map遍历的方式

     

    一、前言

    1、在看 《阿里巴巴java开发手册》时候,有一条推荐的规约: 【推荐】使用entrySet遍历Map类集合KV而不是keySet方式进行遍历。 说明:keySet其实是遍历了2次,一次是转为Iterator对象,另一次是从hashMap中取出key所对应的value。而entrySet只是遍历了一次就把key和value都放到了entry中,效率更高。 ---- 那么如何理解那一段话呢? map 集合如何遍历效率高?

     

     

    二、Map集合的遍历

    1、根据 key 找 value

    • 获取所有的 key 集合。 map.keySet() 
    • 遍历 key 集合。

    • 根据 key 到集合中去找 value 。 map.get(key)

     

    2、根据 key--value 键值对 找键和值

    • 获取所有的 key--value键值对集合。 map.entrySet()
    • 遍历键值对集合,获取每一个键值对对象。
    • 根据键值对对象,获取 key 键 和 value 值。 entry.getKey(); entry.getValue();

     

    3、遍历values 值对象: map.values();

     

    三、代码实现

    1、 遍历测试代码如下:

    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Map.Entry;
    import org.junit.Test;
    /**
    * description: 遍历Map集合效率比较
    * @version v1.0
    * @author w
    * @date 2018年10月23日上午11:20:08
    */
    public class ForeachMap {
        /**
        * description: 初始化map集合中元素
        * @param map
        * @version v1.0
        * @author w
        * @date 2018年10月23日 下午2:45:35
        */
        public void init(Map<Integer, String> map){
            // 初始化map集合中元素的个数
            int count = 1000000;
            for (int i = 1; i <= count; i++) {
                map.put(i, i+ " ---> map");
            }
        }
    
        @Test
        public void test(){
            Map<Integer, String> map = new HashMap<>();
            Map<Integer, String> map2 = new HashMap<>();
            long start = System.currentTimeMillis();
            init(map);
            init(map2);
            System.out.println("装载map耗时: "+(System.currentTimeMillis()-start)+ " ms");
    
            start = System.currentTimeMillis();
            foreachKeyset(map);
            System.out.println("foreachKeyset 遍历 map耗时: "+(System.currentTimeMillis()-start)+ " ms");
        
            start = System.currentTimeMillis();
            foreachEntry(map2);
            System.out.println("foreachEntry 遍历 map耗时: "+(System.currentTimeMillis()-start)+ " ms");
    
            start = System.currentTimeMillis();
            iteratorEntry(map2);
            System.out.println("iteratorEntry 遍历 map耗时: "+(System.currentTimeMillis()-start)+ " ms");
            System.out.println(map.size());
        }
    
        /**
        * description: 根据 key 找 value
        * @param map
        * @version v1.0
        * @author w
        * @date 2018年10月23日 下午5:10:01
        */
        private void foreachKeyset(Map<Integer, String> map) {
            for(Integer key : map.keySet()){
                String value = map.get(key);
                // System.out.println("foreachKeyset : key :" + key + "---> value :"+ value);
            }
        }
    
        /**
        * description: 根据 key--value 键值对 找键和值 ( foreach 遍历)
        * @param map
        * @version v1.0
        * @author w
        * @date 2018年10月23日 下午5:19:31
        */
        private void foreachEntry(Map<Integer, String> map) {
            for(Entry<Integer, String> entry : map.entrySet()){
            // System.out.println("foreachEntry : key :" + entry.getKey() + "---> value :"+entry.getValue());
            }
        }
    
        /**
        * description: 根据 key--value 键值对 找键和值 ( iterator 遍历)
        * @param map
        * @version v1.0
        * @author w
        * @date 2018年10月23日 下午5:19:01
        */
        private void iteratorEntry(Map<Integer, String> map) {
            Iterator<Entry<Integer, String>> iterator = map.entrySet().iterator();
            while(iterator.hasNext()){
                Entry<Integer, String> entry = iterator.next();
                // System.out.println("iteratorEntry : key :" + entry.getKey() + "---> value :"+entry.getValue());
            }
        }
    
    }

     

    2、运行结果:

    装载map耗时: 2705 ms

    foreachKeyset 遍历 map耗时: 44 ms

    foreachEntry 遍历 map耗时: 22 ms

    iteratorEntry 遍历 map耗时: 17 ms

    1000000

     

    四、总结

    1、遍历 map 集合时,应该同时遍历出 键值对,这样效率更高。

    2、若遍历过程中,需要根据条件删除集合中元素,参考:https://blog.csdn.net/HaHa_Sir/article/details/80295755

     

     

     

    参考资料: https://blog.csdn.net/zhangsify/article/details/52966094#commentBox

     

     

     

     

    展开全文
  • Java Map集合面试题汇总

    千次阅读 2018-04-20 21:00:32
    转载自 Java Map集合面试题汇总1、 你都知道哪些常用的Map集合?2、Collection集合接口和Map接口有什么关系?3、HashMap是线程安全的吗?线程安全的Map都有哪些?性能最好的是哪个?4、使用HashMap有什么性能问题吗...

    转载自 Java Map集合面试题汇总

    1、 你都知道哪些常用的Map集合?


    2、Collection集合接口和Map接口有什么关系?


    3、HashMap是线程安全的吗?线程安全的Map都有哪些?性能最好的是哪个?


    4、使用HashMap有什么性能问题吗?


    5、HashMap的数据结构是怎样的?默认大小是多少?内部是怎么扩容的?


    6、怎么按添加顺序存储元素?怎么按A-Z自然顺序存储元素?怎么自定义排序?


    7、HashMap的链表结构设计是用来解决什么问题的?


    8、HashMap的键、值可以为NULL吗?HashTable呢?


    9、HashMap使用对象作为key,如果hashcode相同会怎么处理?


    10、HashMap中的get操作是什么原理?


    答案见下面留言处,有异议也欢迎大家在下面留言,觉得有用的可以转发到朋友圈,一起学习。


    展开全文
  • java Map集合嵌套,value为Map和value为List 2013年12月13日 23:13:34wuer0520阅读数:12476 import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import ...
  • Java map集合深入学习

    万次阅读 多人点赞 2018-10-29 00:12:48
      概要: java.util 中的集合类包含 Java 中某些最常用的类。...本文主要介绍java map的初始化、用法、map的四种常用的遍历方式、map的排序以及常用api。 目录 1Map用法 类型介绍 类型区别 ...
  • Java map集合的两种取出方式

    千次阅读 2016-04-22 15:59:08
    Java map集合的两种取出方式
  • Java Map集合遍历的三种方法

    千次阅读 2016-07-22 19:39:54
    java集合的一个很重要的操作—遍历,下面来看看Java map集合遍历的几种方法 预先创建一个Map Map, Student> map = new HashMap, Student>(); map.put("1001", "小张"); map.put("1002", "小明"); map.put("1003...
  • Java Map 集合类简介

    千次阅读 2011-01-30 10:24:00
    <br />Java Map 集合类简介 作者:Jack Shirazi 了解最常用的集合类型之一 Map 的基础知识以及如何针对您应用程序特有的数据优化 Map 。 本文相关下载: · Jack 的 HashMap ...
  • Java Map集合习题答案

    千次阅读 2019-07-11 23:46:08
    基础题 ...二、说出Entry键值对对象遍历Map集合的原理。 Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map中是一一对应关系,这一对对象又称做Map 中的一个Entry(项)。E...
  • Java Map集合获取字符串中的字母出现的次数
  • Java Map集合的详解

    万次阅读 多人点赞 2016-07-27 21:43:33
    一,Map 先说一下Map吧~ 如果程序中存储了几百万个学生,而且经常需要使用学号来搜索某个学生,那么这个需求有效的数据结构就是MapMap是一种依照键(key)存储元素的容器,键(key)很像下标,在List中下标是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,944
精华内容 13,177
关键字:

javamap集合

java 订阅