关于Map的九大问题, HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap

关于Map的九大问题 http://itxxz.iteye.com/blog/2102597
0、将Map转换为List类型

在java中Map接口提供了三种集合获取方式:Key set,,value set, and key-value set.。它们都可以通过构造方法或者addAll()方法来转换为List类型。下面代码就说明了如何从Map中构造ArrayList:

1、通过Entry 遍历Map
java中这种以键值对存在的方式被称为Map.Entry。Map.entrySet()返回的是一个key-value 集合,这是一种非常高效的遍历方式。

Iterator 我们也经常用到,尤其是在JDK1.5以前

2、通过Key来对Map排序
排序需要对Map的ke进行频繁的操作,一种方式就是通过比较器(comparator )来实现:

另外一种方法就是通过SortedMap,但必须要实现Comparable接口。

3、对value对Map进行排序
这与上一点有些类似,代码如下:

4、初始化一个static 的常量Map
当你希望创建一个全局静态Map的时候,我们有以下两种方式,而且是线程安全的。
而在Test1中,我们虽然声明了map是静态的,但是在初始化时,我们依然可以改变它的值,就像Test1.map.put(3,”three”);
在Test2中,我们通过一个内部类,将其设置为不可修改,那么当我们运行Test2.map.put(3,”three”)的时候,它就会抛出一个UnsupportedOperationException 异常来禁止你修改。

5、HashMap, TreeMap, and Hashtable之间的不同
在Map接口中,共有三种实现:HashMap,TreeMap,Hashtable。
它们之间各有不同,详细内容请参考 HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap. 一文。

6、Map中的反向查询
我们在Map添加一个键值对后,意味着这在Map中键和值是一一对应的,一个键就是对应一个值。但是有时候我们需要反向查询,比如通过某一个值来查找它的键,这种数据结构被称为bidirectional map,遗憾的是JDK并没有对其支持。
Apache和Guava 共同提供了这种bidirectional map实现,它在实现中它规定了键和值都是必须是1:1的关系。

7、对Map的复制
java中提供了很多方法都可以实现对一个Map的复制,但是那些方法不见得会时时同步。简单说,就是一个Map发生的变化,而复制的那个依然保持原样。下面是一个比较高效的实现方法:

Java代码
  1. Map copiedMap = Collections.synchronizedMap(map);

当然还有另外一个方法,那就是克隆。但是我们的java鼻祖Josh Bloch却不推荐这种方式,他曾经在一次访谈中说过关于Map克隆的问题:在很多类中都提供了克隆的方法,因为人们确实需要。但是克隆非常有局限性,而且在很多时候造成了不必要的影响。(原文《Copy constructor versus cloning》)

8、创建一个空的Map
如果这个map被置为不可用,可以通过以下实现

Java代码
  1. map = Collections.emptyMap();

相反,我们会用到的时候,就可以直接
map = new HashMap();

HashMap vs. TreeMap vs. Hashtable vs. LinkedHashMap
http://www.itxxz.com/a/tea/2014/0811/192.html

Map是最重要的数据结构。这篇文章中,我会带你们看看HashMap, TreeMap, HashTable和LinkedHashMap的区别。

1. Map概览

Java SE中有四种常见的Map实现——HashMap, TreeMap, Hashtable和LinkedHashMap。如果我们使用一句话来分别概括它们的特点,就是:
HashMap就是一张hash表,键和值都没有排序
TreeMap以红-黑树结构为基础,键值按顺序排列
LinkedHashMap保存了插入时的顺序
Hashtable同步的(而HashMap是不同步的)。所以如果在线程安全的环境下应该多使用HashMap,而不是Hashtable,因为Hashtable对同步有额外的开销。

2. HashMap
如果HashMap的键(key)是自定义的对象,那么需要按规则定义它的equals()和hashCode()方法。

输出:

4
white dog – 5
black dog – 15
red dog – 10
white dog – 20
注意,我们错误的将”white dogs”添加了两次,但是HashMap却接受了两只”white dogs”。这不合理(因为HashMap的键不应该重复),我们会搞不清楚真正有多少白色的狗存在。 Dog类应该定义如下:

现在输出结果如下:

3
red dog – 10
white dog – 20
black dog – 15
输出结果如上是因为HashMap不允许有两个相等的元素存在。默认情况下(也就是类没有实现hashCode()和equals()方法时),会使用Object类中的这两个方法。Object类中的hashCode()对于不同的对象会返回不同的整数,而只有两个引用指向的同样的对象时equals()才会返回true。。

来看看HashMap最常用的方法,如迭代、打印等。

3. TreeMap

TreeMap的键按顺序排列。让我们先看个例子看看什么叫作“键按顺序排列”。

输出:

Exception in thread “main” java.lang.ClassCastException: collection.Dog cannot be cast to java.lang.Comparable
at java.util.TreeMap.put(Unknown Source)
at collection.TestHashMap.main(TestHashMap.java:35)
因为TreeMap按照键的顺序进行排列对象,所以键的对象之间需要能够比较,所以就要实现Comparable接口。你可以使用String作为键,String已经实现了Comparable接口。

我们来修改下Dog类,让它实现Comparable接口。

输出:

red dog – 10
black dog – 15
white dog – 20
结果根据键的排列顺序进行输出,在我们的例子中根据size排序的。

如果我们将“Dog d4 = new Dog(“white”, 10);”替换成“Dog d4 = new Dog(“white”, 40);”,那么输出会变成:

white dog – 20
red dog – 10
black dog – 15
white dog – 5
这是因为TreeMap使用compareTo()方法来比较键值的大小,size不相等的狗是不同的狗。

4. Hashtable

Java文档写道:

HashMap类和Hashtable类几乎相同,不同之处在于HashMap是不同步的,也允许接受null键和null值。

5. LinkedHashMap

LinkedHashMap is a subclass of HashMap. That means it inherits the features of HashMap. In addition, the linked list preserves the insertion-order.

Let’s replace the HashMap with LinkedHashMap using the same code used for HashMap.

LinkedHashMap是HashMap的子类,所以LinkedHashMap继承了HashMap的一些属性,它在HashMap基础上增加的特性就是保存了插入对象的顺序。

输出:

red dog – 10
black dog – 15
white dog – 20
如果我们使用HashMap的话,输出将会如下,会打乱并插入的顺序:
red dog – 10
white dog – 20
black dog – 15