Java 容器 & 泛型:五、HashMap 和 TreeMap的自白
Writer:BYSocket(泥沙砖瓦浆木匠)
微博:BYSocket
豆瓣:BYSocket
Java 容器的文章这次应该是最后一篇了:Java 容器 系列。 今天泥瓦匠聊下 Maps。
一、Map回顾
Map,又称映射表,是将键映射到值的对象。有四种实现Map接口并且经常使用的Map集合为:HashMap,TreeMap,Hashtable 和 LinkedHashMap.
泥瓦匠记忆宫殿:
1、一个映射不包含重复的键。
2、每个键最多只能映射到一个值。
二、HashMap
HashMap是基于哈希表的Map接口的实现。其对键进行散列,散列函数只能作用于键。下面模拟下,公司员工和找员工的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import java.util.HashMap; import java.util.Map; class Employee {} public class HaspMap01 { public static void main(String[] args) { Map< String , Employee> employees = new HashMap< String , Employee>(); employees.put("1206010035", new Employee()); System.out.println(employees); String number = "1206010035"; System.out.println(employees.get(number)); } } |
Run一下,大家可以见到结果:put方法,可以将键值映射添加进表。get方法则返回指定键所映射的值。从他们 hashCode 可以看出是同一个对象。
HaspMap的键必须唯一,同样其同一个键不能存放两个值,如果对同一个键两次调用put方法,第二个值会取代第一个值。同样是允许使用 null 值和 null 键。下面泥瓦匠用一个简单的例子解释下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package javaBasic.collection.map; import java.util.HashMap; import java.util.Map; public class HaspMap02 { @SuppressWarnings({ "unchecked", "rawtypes" }) public static void main(String[] args) { Map map = new HashMap< String , String>(); map.put(null, "null01"); map.put(null, "null02"); System.out.println(map); System.out.println(map.get(null)); } } |
结果如下:
1
2
|
{null=null02} null02 |
由此可见,第一个值被第二个值所替换了。
下面有三点是HashMap重要之处:
1、HashMap的构造函数
HaspMap构造函数涉及两个参数:初始容量和加载因子。初试容量是哈希表创建时的其中桶的含量。加载因子是哈希表在其容量自动增加之前可以达到多满的一种尺度。这两个参数都是影响HashMap的性能。默认构造一个具有默认初始容量 (16) 和默认加载因子 (0.75)。默认加载因子 (.75) 在时间和空间成本上是一种折衷的考虑。
2、和上次总结的Set都差不多,这个HashMap线程是不安全不同步的。如果想防止意外发生,则设置成同步即可:
1Map m = Collections.synchronizedMap(new HashMap(...));
3、不同步的话,意味着存在快速失败导致的并发修改异常。
下面看一个复杂例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
|
package javaBasic.collection.map; import java.util.HashMap; import java.util.Map.Entry; class A { public boolean equals(Object obj) { return true; } } class B { public int hashCode() { return 1; } } class C { public int hashCode() { return 2; } public boolean equals(Object obj) { return true; } } public class HashMap03 { public static void main(String[] args) { HashMap< A , Integer> hashMapA = new HashMap< A , Integer>(); hashMapA.put(new A(), 10); hashMapA.put(new A(), 5); System.out.println("HashMapA Elements:"); System.out.print("\t" + hashMapA + "\n"); // loop HashMapA for(Entry< A , Integer> entryA : hashMapA.entrySet()) { System.out.println(entryA.getKey().toString()+"-"+entryA.getValue()); } HashMap< B , Integer> hashMapB = new HashMap< B , Integer>(); hashMapB.put(new B(), 10); hashMapB.put(new B(), 5); System.out.println("HashMapB Elements:"); System.out.print("\t" + hashMapB + "\n"); // loop HashMapB for(Entry< B , Integer> entryB : hashMapB.entrySet()) { System.out.println(entryB.getKey().toString()+"-"+entryB.getValue()); } HashMap< C , Integer> hashMapC = new HashMap< C , Integer>(); hashMapC.put(new C(), 10); hashMapC.put(new C(), 5); System.out.println("HashMapC Elements:"); System.out.print("\t" + hashMapC + "\n"); // loop HashMap for(Entry< C , Integer> entryC : hashMapC.entrySet()) { System.out.println(entryC.getKey().toString()+"-"+entryC.getValue()); } } } |
运行一下,可以看到以下结果:
由此可见,其中和 Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较 中涉及的知识点一致:
集合判断两个元素相等不单单是equals方法,并且必须hashCode()方法返回值也要相等。
三、TreeMap
TreeMap使用树结构实现(红黑树),集合中的元素进行排序,但是添加、删除和包含的算法复杂度为O(log(n))。其实Map特性基本都是一致的,比如看下面的简单例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
public class TreeMap01 { @SuppressWarnings({ "rawtypes", "unchecked" }) public static void main(String[] args) { Map map = new TreeMap(); map.put("1", "1"); map.put("4", "4"); map.put("2", "2"); map.put("2", "3"); System.out.println(map); } } |
结果如下:
1
|
{1=1, 2=3, 4=4} |
从中我们可以看出
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没有调优选项,因为该树总处于平衡状态。
Writer:BYSocket(泥沙砖瓦浆木匠)
微博:BYSocket
豆瓣:BYSocket
Java 容器 & 泛型:五、HashMap 和 TreeMap的自白的更多相关文章
- Java 容器 & 泛型:一、认识容器
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 容器是Java语言学习中重要的一部分.泥瓦匠我的感觉是刚开始挺难学的,但等你熟悉它,接触多了,也就“顺 ...
- Java 对比Hashtable、Hashmap、Treemap有什么不同?
①基本理解 Hashtable.Hashmap.Treemap都是最常见的一些Map实现,是以键值对的形式存储和操作数据的容器类型. Hashtable是Java类库提供的一个哈希实现,本身是同步的, ...
- Java 容器源码分析之 TreeMap
TreeMap 是一种基于红黑树实现的 Key-Value 结构.在使用集合视图在 HashMap 中迭代时,是不能保证迭代顺序的: LinkedHashMap 使用了双向链表,保证按照插入顺序或者访 ...
- java面试题之HashMap和TreeMap的区别
HashMap和TreeMap的区别 相同点: 都是以key和value的形式存储: key不可以重复: 都是线程不安全的: 不同点: HashMap的key可以为空 TreeMap的key值是有序的 ...
- Java 中HashTable、HashMap、TreeMap三者区别,以及自定义对象是否相同比较,自定义排序等
/* Map集合:该集合存储键值对.一对一对往里存.而且要保证键的唯一性. Map |--Hashtable:底层是哈希表数据结构,不可以存入null键null值.该集合是线程同步的.效率低.基本已废 ...
- Java 容器 & 泛型:三、HashSet,TreeSet 和 LinkedHashSet比较
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 上一篇总结了下ArrayList .LinkedList和Vector比较,今天泥瓦匠总结下Hash ...
- java容器三:HashMap源码解析
前言:Map接口 map是一个存储键值对的集合,实现了Map接口的主要类有以下几种 TreeMap:用红黑树实现 HashMap:数组和链表实现 HashTable:与HashMap类似,但是线程安全 ...
- Java 容器 & 泛型:六、容器讲到为什么要使用泛型
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket ArrayList是集合类中无处不在的,泛型也是,泛型对集合类尤其有用.但是为啥要使用泛型?理解好了这 ...
- Java 容器 & 泛型:四、Colletions.sort 和 Arrays.sort 的算法
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket 本来准备讲 Map集合 ,还是喜欢学到哪里总结吧.最近面试期准备准备,我是一员,成功被阿里在线笔试秒杀 ...
随机推荐
- ORA-01017 invalid username/password;logon denied
一般来说这个是密码丢失问题,但也许是因为你的用户名或密码写错啦,所以先检查下用户名和密码,觉得没错的话就去查看 sqlnet.ora (在 安装盘下面的:oracle\product\11.2.0\d ...
- 五分钟让你读懂UML常见类图
相信各位同学在阅读一些源码分析类文章或是设计应用架构时没少与UML类图打交道.实际上,UML类图中最常用到的元素五分钟就能掌握,经常看到UML类图但还不太熟悉的小伙伴赶紧来一起认识一下它吧:) 一 ...
- babel简介
1.babel是什么 babel官网正中间一行黄色大字写着“babel is a javascript compiler”,翻译一下就是babel是一个javascript转译器.为什么会有babel ...
- springcloud+zuul+swagger 分布式接口文档
https://gitee.com/didispace/swagger-butler 1.引用上面项目中的swagger 工具包 2.zuul 网关配置 zuul.routes.api-apiserv ...
- 压力测试工具 Apache_jmeter软件配置+TCP示例说明
该软件jmeter是Apache官方开源压力测试软件. jmeter官网:http://jmeter.apache.org/ . 本文使用的版本是 3.0版本, 它需要jdk7及以上版本支持. 网 ...
- webveiw返回死循环问题以及在打开web页面会唤起浏览器打开的问题解决
微信.QQ空间等大量软件都内嵌了H5,不得不说这是一种趋势,Andriod与H5互调可以让我们实现混合开发.至于混合开发就是在一个App中内嵌一个轻量级的浏览器,一部分原生的功能改为Html 5来开发 ...
- 底图与蒙版的过渡效果transition
我用2种方法写了底图与蒙版的过渡效果 方法一:用js方法 <!DOCTYPE html> <html> <head> <meta http-equiv=&qu ...
- div+css+position实现简单的纵向导航栏
完成效果: 这应该是很简单的纵向导航栏了. OK,进入正题 首先,我们看上面的效果图可以分析得出,要实现这个效果需要用到的技术点 1.hover 2.position 3.布局 我认为在这个效果的实现 ...
- js中创建对象的5种方法
1.原始模式 var dog = { name: jack, length: 70, wang:function(){ console.log(this.name); } 2.工厂模式(批量) fun ...
- JS中获取CSS样式的方法
1.对于内联样式,可以直接使用ele.style.属性名(当然也可以用键值对的方式)获得.注意在CSS中单词之间用-连接,在JS中要用驼峰命名法 如 <div id="dv" ...