一般来说,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. StackExchange.Redis通用封装类分享

    前两天朋友问我,有没有使用过StackExchange.Redis,问我要个封装类,由于之前都是使用ServiceStack.Redis,由于ServiceStack.Redis v4版本后是收费版的 ...

  2. iOS 阶段学习第11天笔记(OC基础知识)

    iOS学习(OC语言)知识点整理 一.OC基础知识 1)#import  用于导入头文件,预处理阶段加载引用,只加载一次. 2)OC 依赖于Foundation框架下的头文件Foundation.h, ...

  3. 【Java每日一题】20161019

    20161018问题解析请点击今日问题下方的"[Java每日一题]20161019"查看 package Oct2016; import java.util.List; publi ...

  4. SDL教程第一和第二个视频的笔记

    观看正月点灯笼的SDL教程,地址http://www.tudou.com/listplay/9eG9tkk91oQ.html #include <stdio.h> #include < ...

  5. 管理系统-------------SSH框架书写登录和显示用户

    一.思路的穿插. web.xml中的配置找到--->application.xml---->找到对应的Action---->找到struts.xml----->在去找actio ...

  6. rabbitMQ publish丢包分析

    rabbitMQ publish丢包分析

  7. p7-p8面试经验总结--拿到offer

    简单的介绍下p7-p8之间的面试经验 整体的过程基本上所有的面试都是类似的,分为如下: 1.自我介绍: 2.相关问题讨论和交流: 3.谈薪资: 0.去面试的是架构师,最后来了两个面试官.最后拿到off ...

  8. 解决MVC4发布在IIS7后,路径无法访问.apk文件的解决方法

    随着智能手机的普及,越来越多的人使用手机上网,很多网站也应手机上网的需要推出了网站客户端,.apk文件就是安卓(Android)的应用程序后缀名,默认情况下,使用IIS作为Web服务器的无法下载此文件 ...

  9. HTML中网页超链接设计

    一.超链接的概念: 1>用<a>标签实现.href属性设置了要链接的网址. 链接路径URL:Uniform Resource Locator的缩写.统一资源定位符. 4部分组成:协议 ...

  10. Popmotion – 小巧,灵活的 JavaScript 运动引擎

    Popmotion 是一个只有12KB的 JavaScript 运动引擎,可以用来实现动画,物理效果和输入跟踪.原生的DOM支持:CSS,SVG,SVG路径和DOM属性的支持,开箱即用.Popmoti ...