关于Java中的Map相关的使用
来源:互联网 发布:金字塔软件下载 编辑:程序博客网 时间:2024/06/06 02:42
上班快两个月,Java很多地方还不算特别清晰,但是遇到了几个关于Map的地方,简单总结一下。
1、为什么要使用Map<Integer,String> m = new HashMap<Integer, String>();这种方式而不是HashMap<Integer,String> m = new HashMap<Integer, String>();
一直看公司里的其他人是这么写的,于是自己也这么写,但是从来没有想过为什么要这么写。后来偶然逛论坛时发现有人提这个问题,但是自己从来没有想过这个问题,实在羞愧。。。。
其实这么写的目的是为了保证代码的可扩展性,可扩展性这个东西说起来似乎很虚,但是工作之后的确会发现需求是在不断发生变化的,因此代码良好的可扩展性对于代码而言实际上是一种必然的要求。
这么写的目的实际上是OO设计中的“面向接口编程”的完美体现。Map是一个接口,而HashMap是一个类,这种方式能够保证在需求发生变化时,可以换成其他的Map,如TreeMap、ConcurrenMap等,这样就可以修改比较少的代码来换取新功能的实现。
这种思想在设计模式“策略模式”中有比较好的体现。可以参见《Head First Pattern》的第一章。
2、HashMap的遍历方式
HashMap应该是工作中使用的比较频繁的一个类,而这个类的遍历方式有两种。
2.1 通过遍历HashMap的keySet来进行遍历
Map<Integer,String> m = new HashMap<Integer, String>();m.put(1, "a");m.put(2, "b");m.put(3, "c");for(Integer i : m.keySet()){System.out.println(m.get(i));}
可以看看keySet()方法的源码,在AbstractMap中具体实现
public Set<K> keySet() {if (keySet == null) { keySet = new AbstractSet<K>() {public Iterator<K> iterator() { return new Iterator<K>() {private Iterator<Entry<K,V>> i = entrySet().iterator();public boolean hasNext() { return i.hasNext();}public K next() { return i.next().getKey();}public void remove() { i.remove();} };}public int size() { return AbstractMap.this.size();}public boolean contains(Object k) { return AbstractMap.this.containsKey(k);} };}return keySet; }
这里实际上是调用了HashMap的entrySet()方法返回一个Set<Map.Entry<K,V>>然后调用这个set的iterator()方法来进行遍历。
2.2 使用HashMap的entrySet来进行遍历
Map<Integer,String> m = new HashMap<Integer, String>();m.put(1, "a");m.put(2, "b");m.put(3, "c");for(Map.Entry<Integer, String> me : m.entrySet()){System.out.println(me.getKey()+" "+me.getValue());}
这种方式是调用HashMap的entrySet方法,这个方法和第一种方法一样返回一个Set<Map.Entry<K,V>>,但是HashMap中的所有数据都直接存储在这个Entry里了。
2.3 这两种方法的效率对比
当只需要将HashMap中的key值取出来的时候,显然直接使用keySet()方法会效率高;而当在遍历的过程中需要去除value值就会使得第二种方法的效率大大降低,因为这相当于遍历HashMap两次。因为在用get()方法时会多次调用equals()方法和hasCode()方法。
3、HashMap在遍历过程中删除元素
使用Map.Entry进行删除元素:
Map<Integer,String> m = new HashMap<Integer, String>();m.put(1, "a");m.put(2, "b");m.put(3, "c");for(Map.Entry<Integer, String> me : m.entrySet()){if(me.getKey() == 2)m.remove(me.getKey());}
运行结果:
Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)at java.util.HashMap$EntryIterator.next(HashMap.java:834)at java.util.HashMap$EntryIterator.next(HashMap.java:832)at com.wxg.testMap.main(testMap.java:13)
使用keySet()来删除元素:
Map<Integer,String> m = new HashMap<Integer, String>();m.put(1, "a");m.put(2, "b");m.put(3, "c");for(Integer i : m.keySet()){if(i == 2)m.remove(i);}运行结果:
Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)at java.util.HashMap$KeyIterator.next(HashMap.java:828)at com.wxg.testMap.main(testMap.java:13)
使用Iterator来删除元素:
Map<Integer,String> m = new HashMap<Integer, String>();m.put(1, "a");m.put(2, "b");m.put(3, "c");Iterator<Map.Entry<Integer, String>> i = m.entrySet().iterator();while(i.hasNext()){Map.Entry<Integer, String> entry = i.next();if(entry.getKey() == 2)i.remove();System.out.println(m.get(2));}
运行结果:
bnullnull
在前两种方法中都抛出了ConCurrentModificationException的异常,这种异常出现的结果就是在remove的时候调用HashMap的removeEntryForKey的时候需要判断modCount和expectedModeCount是否相等,不相等的话就会抛出这个异常。
而在Iterator的remove方法中对这两个变量做了同步,所以不会抛出这个异常。
- 关于Java中的Map相关的使用
- 关于Java中的map的理解
- 关于Set、List、Map的区别 -- JAVA 后台相关
- Java:关于使用Map的一些知识
- java中的Map.Entry接口的使用
- 关于map的使用
- 关于C#访问JAVA中的map类型的体会
- Java中关于Map经常使用的方法
- java中关于Collection和Map相关的类&接口之间的关系
- 关于JAVA中的基本数据类型的转换相关问题
- java Map的使用
- java map的使用
- java Map的使用
- java map的使用
- 关于MAP文件的使用
- c++ 关于map的使用
- 关于MAP文件的使用
- 关于Map集合的使用
- 2014年Android面试题
- RPG游戏地图设计与实现
- 数据在计算机中的存储(字节序,浮点数)
- Java中的软(弱)引用
- CSS之Position详解(转载自cnblogs)
- 关于Java中的Map相关的使用
- C3PO与oracle数据库
- Python正则表达式详解
- strstr函数
- CodeForces 233A
- UVa OJ 105 - The Skyline Problem
- 集合框架2
- Android Matrix 介绍
- 【iOS开发-22】navigationBar导航条和navigationItem设置:基本搞定导航条上的文字和按钮以及各种跳转