天天看点

Java 容器 & 泛型:五、HashMap 和 TreeMap的自白一、Map回顾二、HashMap三、TreeMap 四、总结

    map,又称映射表,是将键映射到值的对象。有四种实现map接口并且经常使用的map集合为:hashmap,treemap,hashtable 和 linkedhashmap.

泥瓦匠记忆宫殿:     1、一个映射不包含重复的键。     2、每个键最多只能映射到一个值。
Java 容器 & 泛型:五、HashMap 和 TreeMap的自白一、Map回顾二、HashMap三、TreeMap 四、总结

    hashmap是基于哈希表的map接口的实现。其对键进行散列,散列函数只能作用于键。下面模拟下,公司员工和找员工的例子:

<a href="http://www.bysocket.com/?p=273#">?</a>

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

<code>import java.util.hashmap;</code>

<code>import java.util.map;</code>

<code>class employee</code>

<code>{}</code>

<code>public class haspmap01</code>

<code>{</code>

<code>    </code><code>public static void main(string[] args)</code>

<code>    </code><code>{</code>

<code>        </code><code>map&lt;</code><code>string</code><code>, employee&gt; employees = new hashmap&lt;</code><code>string</code><code>, employee&gt;();</code>

<code>        </code><code>employees.put("1206010035", new employee());</code>

<code>        </code><code>system.out.println(employees);</code>

<code>        </code> 

<code>        </code><code>string number = "1206010035";</code>

<code>        </code><code>system.out.println(employees.get(number));</code>

<code>    </code><code>}</code>

<code>}</code>

    haspmap的键必须唯一,同样其同一个键不能存放两个值,如果对同一个键两次调用put方法,第二个值会取代第一个值。同样是允许使用 null 值和 null 键。下面泥瓦匠用一个简单的例子解释下:

<code>package javabasic.collection.map;</code>

<code>public class haspmap02</code>

<code>    </code><code>@suppresswarnings({ "unchecked", "rawtypes" })</code>

<code>        </code><code>map map = new hashmap&lt;</code><code>string</code><code>, string&gt;();</code>

<code>        </code><code>map.put(null, "null01");</code>

<code>        </code><code>map.put(null, "null02");</code>

<code>        </code><code>system.out.println(map);</code>

<code>        </code><code>system.out.println(map.get(null));</code>

结果如下:

<code>{null=null02}</code>

<code>null02</code>

由此可见,第一个值被第二个值所替换了。

下面有三点是hashmap重要之处:

1、hashmap的构造函数    haspmap构造函数涉及两个参数:初始容量和加载因子。初试容量是哈希表创建时的其中桶的含量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。这两个参数都是影响hashmap的性能。默认构造一个具有默认初始容量 (16) 和默认加载因子 (0.75)。默认加载因子 (.75) 在时间和空间成本上是一种折衷的考虑。 2、和上次总结的set都差不多,这个hashmap线程是不安全不同步的。如果想防止意外发生,则设置成同步即可: <code>map m = collections.synchronizedmap(new hashmap(...));</code> 3、不同步的话,意味着存在快速失败导致的并发修改异常。

下面看一个复杂例子:

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

<code>import java.util.map.entry;</code>

<code>class a</code>

<code>    </code><code>public boolean equals(object obj)</code>

<code>        </code><code>return true;</code>

<code>class b</code>

<code>    </code><code>public int hashcode()</code>

<code>        </code><code>return 1;</code>

<code>class c</code>

<code>        </code><code>return 2;</code>

<code>public class hashmap03</code>

<code>        </code><code>hashmap&lt;</code><code>a</code><code>, integer&gt; hashmapa = new hashmap&lt;</code><code>a</code><code>, integer&gt;();</code>

<code>        </code><code>hashmapa.put(new a(), 10);</code>

<code>        </code><code>hashmapa.put(new a(), 5);</code>

<code>        </code><code>system.out.println("hashmapa elements:");</code>

<code>        </code><code>system.out.print("\t" + hashmapa + "\n");</code>

<code>        </code><code>// loop hashmapa</code>

<code>        </code><code>for(entry&lt;</code><code>a</code><code>, integer&gt; entrya : hashmapa.entryset())</code>

<code>        </code><code>{</code>

<code>            </code><code>system.out.println(entrya.getkey().tostring()+"-"+entrya.getvalue());</code>

<code>        </code><code>}</code>

<code>        </code><code>hashmap&lt;</code><code>b</code><code>, integer&gt; hashmapb = new hashmap&lt;</code><code>b</code><code>, integer&gt;();</code>

<code>        </code><code>hashmapb.put(new b(), 10);</code>

<code>        </code><code>hashmapb.put(new b(), 5);</code>

<code>        </code><code>system.out.println("hashmapb elements:");</code>

<code>        </code><code>system.out.print("\t" + hashmapb + "\n");</code>

<code>        </code><code>// loop hashmapb</code>

<code>        </code><code>for(entry&lt;</code><code>b</code><code>, integer&gt; entryb : hashmapb.entryset())</code>

<code>            </code><code>system.out.println(entryb.getkey().tostring()+"-"+entryb.getvalue());</code>

<code>        </code><code>hashmap&lt;</code><code>c</code><code>, integer&gt; hashmapc = new hashmap&lt;</code><code>c</code><code>, integer&gt;();</code>

<code>        </code><code>hashmapc.put(new c(), 10);</code>

<code>        </code><code>hashmapc.put(new c(), 5);</code>

<code>        </code><code>system.out.println("hashmapc elements:");</code>

<code>        </code><code>system.out.print("\t" + hashmapc + "\n");</code>

<code>        </code><code>// loop hashmap</code>

<code>        </code><code>for(entry&lt;</code><code>c</code><code>, integer&gt; entryc : hashmapc.entryset())</code>

<code>            </code><code>system.out.println(entryc.getkey().tostring()+"-"+entryc.getvalue());</code>

运行一下,可以看到以下结果:

集合判断两个元素相等不单单是equals方法,并且必须hashcode()方法返回值也要相等。

    treemap使用树结构实现(红黑树),集合中的元素进行排序,但是添加、删除和包含的算法复杂度为o(log(n))。其实map特性基本都是一致的,比如看下面的简单例子:

<code>public class treemap01</code>

<code>{  </code>

<code>    </code><code>@suppresswarnings({ "rawtypes", "unchecked" })</code>

<code>        </code><code>map map = new treemap();</code>

<code>        </code><code>map.put("1", "1");</code>

<code>        </code><code>map.put("4", "4");</code>

<code>        </code><code>map.put("2", "2");</code>

<code>        </code><code>map.put("2", "3");</code>

<code>{1=1, 2=3, 4=4}</code>

从中我们可以看出

1、treemap实现了sortedmap,顾名思义,其表示为有排序的集合。 2、同样其同一个键不能存放两个值,如果对同一个键两次调用put方法,第二个值会取代第一个值。
hashmap与treemap       1、hashmap通过hashcode对其内容进行快速查找,而treemap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用treemap(hashmap中元素的排列顺序是不固定的)。hashmap中元素的排列顺序是不固定的)。       2、  hashmap通过hashcode对其内容进行快速查找,而treemap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用treemap(hashmap中元素的排列顺序是不固定的)。集合框架”提供两种常规的map实现:hashmap和treemap (treemap实现sortedmap接口)。       3、在map 中插入、删除和定位元素,hashmap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么treemap会更好。使用hashmap要求添加的键类明确定义了hashcode()和 equals()的实现。 这个treemap没有调优选项,因为该树总处于平衡状态。