一般来说,Map是一种由键值对组成的数据结构,其中键(key)在Map中是不能重复的;

本篇文章总结了9个最常见的问题(关于Java Map及其实现类);

出于简单考虑,在代码例子中我将不使用泛型,因此,我将仅仅写上Map而不是写上Map<K, V>,且Map中的Key和Value都是可以比较的,意味着K和V都实现了Comparable接口;

1.Map转List

在Java中,Map接口提供了三个集合视图,即key set, value set,和key-value set。它们都可以转成List集合,如下代码所示:

// key list
List keyList = new ArrayList(map.keySet());
// value list
List valueList = new ArrayList(map.valueSet());
// key-value list
List entryList = new ArrayList(map.entrySet());

2.迭代遍历Map中的key-value

迭代遍历Map中的键值对是最基本的操作。在Java中,键值对信息存储在Map.Entry类中。通过调用Map.entrySet()方法会返回键值对集合,因此最有效的遍历Map中的键值对如下代码所示:

for(Entry entry: map.entrySet()) {
// get key
K key = entry.getKey();
// get value
V value = entry.getValue();
}

当然,也可以通过迭代器遍历,如下代码:

while(itr.hasNext()) {
Entry entry = itr.next();
// get key
K key = entry.getKey();
// get value
V value = entry.getValue();
}

3.Map中的元素按Key排序

对Map中的元素按key排序是另一个经常使用的操作。有一种方法是将Map中的元素放进List集合,然后通过一个比较器对集合进行排序,如下代码示例:

        List list = new ArrayList(map.entrySet());
Collections.sort(list, new Comparator() {
public int compare(Entry e1, Entry e2) {
return e1.getKey().compareTo(e2.getKey());
}
});
}

另一种方法是使用SortedMap,其提供了对Key进行排序的功能;前提是Map中的Key需要实现Comparable接口或者通过构造方法传入比较器;

TreeMap是SortedMap的一个实现类,它的构造方法能够接收一个比较器,以下代码展示了如何将普通Map转成SortedMap:

SortedMap sortedMap = new TreeMap(new Comparator() {
@Override
public int compare(K k1, K k2) {
return k1.compareTo(k2);
}
});
sortedMap.putAll(map);

4.Map中的元素按Value排序

同样可以参考前面的将Map的元素放进List集合然后传入比较器进行排序,不过这次要比较的对象是Entry.getValue()。如下代码所示:

List list = new ArrayList(map.entrySet());
Collections.sort(list, new Comparator() {
@Override
public int compare(Entry e1, Entry e2) {
return e1.getValue().compareTo(e2.getValue());
}
});

对于这个问题,当map中的value都是唯一的情况,我们仍然可以使用sorted map来排序,在这种情况下,你可以将key赋值给value,value赋值给key来实现该功能;但是这种解决方法十分受限,非常不建议使用;

5.初始化一个不可修改的Map

当你想要使用Map来存储一些常量时,将他们存储到一个不可修改的Map是一个好习惯。这种防御性编程技术会帮助你创建一个能安全使用且线程安全的map;

我们可以使用静态代码块来初始化一个静态不可变的map,如下代码:

public class Test {
private static final Map map;
static {
map = new HashMap();
map.put(1, "one");
map.put(2, "two");
}
}

然而以上代码是有问题的,即使map被声明成static final,我们仍然可以操作该map,如Test.map.put(3,"three");因此,这不是不可变的map;

为了创建一个不可变的map,我们需要一个额外的map对象,将它作为入参传入Collections.unmodifiableMap方法中,然后得到一个不可变的Map,如下代码:

public class Test {
private static final Map map;
static {
Map aMap = new HashMap();
aMap.put(1, "one");
aMap.put(2, "two");
map = Collections.unmodifiableMap(aMap);
}
}

此时,当我们运行Test.map.put(3,"three")将抛出UnsupportedOperationException异常;

Google的Guava库支持多种方式创建不可变的Map,想学习的可以参考其官方使用手册;

6.HashMap, TreeMap, 和Hashtable的区别

HashMap, TreeMap, 和Hashtable是Map接口的三个主要实现类,它们之间的主要区别如下:

  • 是否有序。HashMap和HashTable不会保证元素的有序性,随着时间推移,元素的顺序可能会发生改变;然而TreeMap是有序的,会根据自然顺序或依据比较器排序;
  • key- value限制。HashMap允许key和value为null(key只能有一个为null,因为key不能重复)。HashTable不允许key 或value为null;TreeMap如果使用自然顺序或者比较器不允许key为null,使用null key将抛出异常;另外,在TreeMap中value是可以为null的;
  • 是否同步。只有Hashtable是同步的,其它的不是。如果线程安全不在考虑范围的话,强烈建议使用HashTable。

另一个比较完整的比较如下:

它们之间的更多比较信息可参考如下链接:

http://www.programcreek.com/2013/03/hashmap-vs-treemap-vs-hashtable-vs-linkedhashmap/

7.反向查找Map

有时候,我们需要key和value都唯一,这种情况允许我们创建一个双向查找Map,也就是说,可以通过唯一的value去查找唯一的Key,遗憾的是,JDK并不支持该数据结构;

Apache Common Collections 和 Guava 提供了对双向查找Map的支持,被叫做BidiMap和BiMap,它们规定了key和value必须是1对1的关系。

8.Map浅拷贝

大部分Map实现类都提供了构造方法,用于对另外一个Map的复制,但是这个复制操作不是同步的,意味着一个线程在对Map进行复制操作的时候,另一个线程可能会对它结构性的修改(增删该等操作);为了阻止意外的非同步操作,应该事先使用Collections.synchronizedMap()方法去创建一个同步Map,如下:

Map copiedMap = Collections.synchronizedMap(map);

另外一种浅拷贝方法是使用clone()方法,然而它并不被集合框架作者Josh Bloch推荐;他曾在一次访谈中谈到关于”拷贝构造方法VS克隆方法“,他说:

I often provide a public clone method on concrete classes because people expect it. ... It’s a shame that Cloneable is broken, but it happens. ... Cloneable is a weak spot, and I think people should be aware of its limitations.

9.创建一个空Map

如果是不可变Map,使用Collections工具类创建,如下:

map = Collections.emptyMap();

否则,直接new,如下:

map = new HashMap();

译文链接:http://www.programcreek.com/2013/09/top-9-questions-for-java-map/

Java Maps的9个常见问题的更多相关文章

  1. Java编程最差实践常见问题详细说明(2)转

    Java编程最差实践常见问题详细说明(2)转 2012-12-13 13:57:20|  分类: JAVA |  标签:java  |举报|字号 订阅     反射使用不当  错误的写法: Java代 ...

  2. Java编程最差实践常见问题详细说明(1)转

    Java编程最差实践常见问题详细说明(1)转     原文地址:http://www.odi.ch/prog/design/newbies.php 每天在写Java程序, 其实里面有一些细节大家可能没 ...

  3. Java虚拟机详解----JVM常见问题总结

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  4. Java初学者的30个常见问题

    本文回答了30个Java入门级初学者的常见问题. 我可以用%除以一个小数吗? a += b 和 a = a + b 的效果有区别吗? 声明一个数组为什么需要花费大量时间?为什么Java库不用随机piv ...

  5. 关于Java Collections的几个常见问题

    列举几个关于Java Collections的常见问题并给出答案. 1. 什么时候用LinkedList,什么时候用ArrayList? ArrayList是使用数组实现的list,本质上就是数组.A ...

  6. Java编程中的一些常见问题汇总

    转载自  http://macrochen.iteye.com/blog/1393502 每天在写Java程序,其实里面有一些细节大家可能没怎么注意,这不,有人总结了一个我们编程中常见的问题.虽然一般 ...

  7. Java代码规范和一些常见问题

       本文中的代码规范,是Java标准代码规范中的一小部分,在我看来,是最重要的一部分.    理想目标:不需要写注释,不需要和别人介绍,别人就知道你的项目大致是做什么的,每个类大概实现了什么功能. ...

  8. Java集合中Set的常见问题及用法

    在这里演示的案例是衔接Java集合中的List(点击查看)那篇博文的,本节我们学习的Set的用法. Set是Collection的一个重要的子接口,Set中的元素是无序排列的,并且元素不可以重复,被称 ...

  9. 【JAVA】Math.Round()函数常见问题“四舍5入”

    java.lang.Math.Round()使用时候,处理方式整理,方便以后查找   /**  * 测试函数 2014-01-10  */ public class TestMath {     pu ...

随机推荐

  1. javascript类型注意事项

    以下是javascript类型的注意事项: null:表示尚未存在的对象,注意,尽管尚未存在,也是个对象啊,所以用typeof检测一个null值变量的结果是Object:不过,为了便于写if语句,在j ...

  2. 使用NISI制作.Net程序服务安装包

    1.开篇之前先说一说NISI是什么. NSIS(Nullsoft Scriptable Install System)是一个开源的 Windows 系统下安装程序制作程序.它提供了安装.卸载.系统设置 ...

  3. [范例] Firemonkey 弹簧动画

    弹簧动画效果: 不用写任何代码,只需设定下面动画属性: 参考动画曲线: http://monkeystyler.com/guide/Interpolation-and-AnimationType-Il ...

  4. MacOS下如何进行Git的冲突(Conflict)处理

    Git在做merge时经常碰到冲突的问题,多数情况都是用IDE中集成的"解决冲突"工具解决了,但有时不能依赖IDE时,就得回过头来去搞清楚Git的一些基础操作了. mergetoo ...

  5. 利用Yii框架中的collections体验PHP类型化编程

    注:20150514 看过 惠新宸 关于PHP7的PPT后,看到了这一特性将被支持. Scalar Type Declarations function foo(int num) function ...

  6. JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  7. mybaits注解

    基本的增删改 @Insert("insert into t_user values(null,#{username},#{password},#{account})") @Dele ...

  8. JavaWeb前端基础复习笔记系列 一

    课程:孔浩前端视频教程(CMS内容管理系统case) 1.背景知识 ASPCMS,是一个基于asp的CMS.类似于Jeecms是基于Java的.aspcms:http://www.aspcms.com ...

  9. 【JAVA并发编程实战】1、对象的共享

    1.栈封闭 在栈封闭中,只能通过局部变量才能访问对象. 所谓栈封闭就是把变量的声明以及应用都局限在一个局部线程中,在这个局部线程中声明和实例化的对象对于线程外部是不可见的,这个局部线程的栈,无法被任何 ...

  10. HTML 限制文本框只能输入特定字符(比如数字 onkeyup+onafterpaste)

    正则表达式1 <td><asp:TextBox ID="TextBox_username" Width="250" runat="s ...