JavaSE集合(八)之Map
前面给大家介绍了集合家族中的Collection家族,这一篇给大家分享的是集合中的另一个家族就是Map家族。以前的时候学习Map的时候没有很认真的去学习,我觉得很多东西还是不是很清楚。
这次我将总结的非常详细。程序员的道理里,我们风雨无阻!
一、Map接口
1.1、Map概述
Map 的字面翻译是映射(地图就是一种映射)。将键映射到值的对象,一个映射不能包含重复的键(如果有添加有重复的键,后面的会覆盖掉前面的,但是如果是自定义类型必须重写hashCode()和equals()方法),每个键最多只能映射到一个值。
map是Java中提供的一种通用的元素存储方式,它是一种集合类。map集合类用于存储键值对(“键”、“值”)即Map<key,value>,每个键映射到一个值。但要注意的是:key不能重复。所以通过指定的key就可以取出对应的value。
在JavaSE中,对Map的实现主要包括: HashMap, TreeMap, HashTable 和 LinkedHashMap:
- HashMap 使用哈希表(hash table)实现, 在 keys 和/或 values 之中,都是无序的.
- TreeMap 基于红黑树(red-black tree)数据结构实现, 按 key 排序.
- LinkedHashMap 保持者插入顺序.
- Hashtable 与HashMap实现方式一样,但Hashtable属于同步(synchronized)的.
所以如果代码是线程安全的,那么应该使用HashMap,因为Hashtable的同步是有一定量的运行代价的。而现今对于需要同步的Map,使用 ConcurrentHashMap 也比 Hashtable 有更高的效率。
注:map中的key和value都必须是Object(除非指定了泛型)
1.2、Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效。
Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素
1.3、Map集合功能概述
- 添加功能
- * V put(K key,V value):添加元素。
- * 如果键是第一次存储,就直接存储元素,返回null
- * 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
putAll(Map<? extends K,? extends V> m)将指定Map中的键值对复制到Map中- 删除功能
- * void clear():移除所有的键值对元素
- * V remove(Object key):删除指定key所对应的键值对,返回可以所关联的value,如果key不存在,返回null
- 判断功能
- * boolean containsKey(Object key):判断集合是否包含指定的键
- * boolean containsValue(Object value):判断集合是否包含指定的值
- * boolean isEmpty():判断集合是否为空
- 获取功能
- * Set<Map.Entry<K,V>> entrySet():
- * V get(Object key):根据键获取值
- * Set<K> keySet():获取集合中所有键的集合
- * Collection<V> values():获取集合中所有值的集合
- 长度功能
- * int size():返回集合中的键值对的个数
Map中包含一个内部类:Entry。该类封装了一个键值对,它包含了三个方法:
- Object getKey():返回该Entry里包含的key值。
- Object getValeu():返回该Entry里包含的value值。
- Object setValue(V value):设置该Entry里包含的value值,并返回新设置的value值。
1.4、Map实例之遍历
Map的遍历大体有3种:
第一种:遍历Map.entrySet():它的每一个元素都是Map.Entry对象,这个对象中,放着的就是Map中的某一对key-value。
第二种:遍历Map.keySet():它是Map中key值的集合,我们可以通过遍历这个集合来读取Map中的元素。
第三种:遍历Map.values():它是Map中value的集合,我们可以直接通过这个集合遍历Map中的值,却不能读取key。
1)Map集合的遍历之键找值
思路:一是:获取所有键的集合。二是:遍历键的集合,获取到每一个键。三是:根据键找值。
- package com.zyh.Collection.map;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Set;
- public class MapDemo_0010 {
- // Map集合的遍历之键找值
- public static void main(String[] args) {
- Map<String,Integer> map = new HashMap<>();
- map.put("张三",);
- map.put("美女",);
- map.put("帅哥",);
- map.put("流浪汉",);
- /*方式一:使用迭代器
- Set<String> str = map.keySet();
- Iterator<String> it = str.iterator();
- while (it.hasNext()){
- String key = it.next();
- Integer value = map.get(key);
- System.out.println("key="+key+"——value="+value);
- }*/
- //方式二:使用增强for循环
- for (String key:map.keySet()){
- System.out.println("key="+key+"——value="+map.get(key));
- }
- }
- }
MapDemo_0010
2)Map集合的遍历之键值对对象找键和值
思路:一是:获取所有键值对对象的集合。二是:遍历键值对对象的集合,获取到每一个键值对对象。三是:根据键值对对象找键和值。
- package com.zyh.Collection.map;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Set;
- public class MapDemo_0011 {
- //Map集合的遍历之键值对对象找键和值
- public static void main(String[] args) {
- Map<String,Integer> map = new HashMap<>();
- map.put("张三",);
- map.put("美女",);
- map.put("帅哥",);
- map.put("流浪汉",);
- /*方式一:使用迭代器
- Set<Map.Entry<String, Integer>> entry = map.entrySet(); //获取所有的键值对象的集合
- Iterator<Map.Entry<String, Integer>> it = entry.iterator(); //获取迭代器
- while (it.hasNext()){
- Map.Entry<String, Integer> en = it.next(); //获取键值对对象
- String key = en.getKey(); //根据键值对对象获取键
- Integer value = en.getValue(); //根据键值对对象获取值
- System.out.println("key="+key+"——value="+value);
- }*/
- //方式二:使用增强for循环
- for (Map.Entry<String,Integer> en : map.entrySet()){
- String key = en.getKey();
- Integer value = en.getValue();
- System.out.println("key="+key+"——value="+value);
- }
- }
- }
MapDemo_0011
二、HashMap
2.1、HashMap概述
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。它存储的时候是无序的。
HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。
HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。
在java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。
HashMap实际上是一个“链表的数组”的数据结构,每个元素存放链表头结点的数组,即数组和链表的结合体。
HashMap注意事项:
1)HashMap底层维护一个数组,我们向HashMap中所放置的对象实际上是存储在该数组当中。
2)当向HashMap中put一对键值时,它会根据key的hashCode值计算出一个位置,该位置就是此对象准备往数组中存放的位置。
2.2、实例:在HashMap中存储key为Student对象,value为String类型
1)当键是自定义类型时怎么保证唯一性:重写hashCode()和equals()方法,这样我们在存储的时候如果有重复的键,后面的会覆盖后面的。
- package com.zyh.Collection.map;
- import com.zyh.domain.Student;
- import java.util.HashMap;
- public class HashMapDemo_0010 {
- public static void main(String[] args) {
- HashMap<Student,String> hs = new HashMap<>();
- hs.put(new Student("张三",),"上海");
- hs.put(new Student("张三",),"上海");
- hs.put(new Student("李四",),"深圳");
- hs.put(new Student("王五",),"苏州");
- hs.put(new Student("赵六",),"杭州");
- System.out.println(hs);
- }
- }
这里的话就会输出:
分析:首先输出的都是无序的,为什么直接输出map就会打印呢?因为底层重写了toString方法。
查看之后它的父类重写了toString()方法
2.3、HashMap的用法
需求:统计字符串中每个字符出现的次数
- String str = "aaaabbbcccccccccc";
- char[] arr = str.toCharArray(); //将字符串转换成字符数组
- HashMap<Character, Integer> hm = new HashMap<>(); //创建双列集合存储键和值
- for(char c : arr) { //遍历字符数组
- if(!hm.containsKey(c)) { //如果不包含这个键
- hm.put(c, ); //就将键和值为1添加
- }else { //如果包含这个键
- hm.put(c, hm.get(c) + ); //就将键和值再加1添加进来
- }
- //hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
- Integer i = !hm.containsKey(c) ? hm.put(c, ) : hm.put(c, hm.get(c) + );
- }
- for (Character key : hm.keySet()) { //遍历双列集合
- System.out.println(key + "=" + hm.get(key));
- }
2.4、LinkedHashMap
特点:底层是链表实现的可以保证怎么存就怎么取
实例:
- package com.zyh.Collection.map;
- import com.zyh.domain.Student;
- import java.util.LinkedHashMap;
- public class LinkedHashMapDemo_0010 {
- public static void main(String[] args) {
- LinkedHashMap<Student,String> lhs = new LinkedHashMap<>();
- lhs.put(new Student("张三",),"上海");
- lhs.put(new Student("李四",),"深圳");
- lhs.put(new Student("王五",),"苏州");
- lhs.put(new Student("赵六",),"杭州");
- System.out.println(lhs);
- }
- }
结果:
四、TreeMap
4.1、TreeMap概述
TreeMap底层是二叉树数据结构,线程不同步,可用于给Map集合中的键进行排序。
注意:
1)用作key的对象必须实现hashCode和equals方法。
2)不能保证其中的键值对的顺序
3)尽量不要使用可变对象作为它们的key值。
SortedMap接口和TreeMap类的关系
SortedMap接口是Map的子接口,其进一步提供对于键的排序功能。
TreeMap类就是SortedMap接口的实现类。
TreeMap可以对key值进行自然排序或者比较器排序,其用法和TreeSet是一致的。
4.2、用例子来说明TreeMap排序问题
- package com.zyh.Collection.map;
- import com.zyh.domain.Student;
- import java.util.TreeMap;
- public class TreeMapDemo_0010 {
- public static void main(String[] args) {
- TreeMap<Student,String> tm = new TreeMap<>();
- tm.put(new Student("张三",),"上海");
- tm.put(new Student("李四",18),"深圳");
- tm.put(new Student("王五",),"苏州");
- tm.put(new Student("赵六",66),"杭州");
- System.out.println(tm);
- }
- }
当我们执行的时候会出错:
因为key是自定义对象不知道怎么排序,所以这里要实现Comparable接口,重写compareTo方法,或者给TreeMap的构造方法中声明一个比较器。
方式一:实现Comparable接口,重写compareTo方法
实现Comparable接口:
重写compareTo方法:
结果:按年龄排序
方式二:给TreeMap的构造方法中声明一个比较器(测试前把前面Student中的删除掉)
- package com.zyh.Collection.map;
- import com.zyh.domain.Student;
- import java.util.Comparator;
- import java.util.TreeMap;
- public class TreeMapDemo_0010 {
- public static void main(String[] args) {
- TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>() {
- @Override
- public int compare(Student s1, Student s2) {
- int num = s1.getAge()-s2.getAge();
- //s1.getName().compareTo(s2.getName())这里的compareTo方法是String类中的方法
- return num==?s1.getName().compareTo(s2.getName()):num;
- }
- });
- tm.put(new Student("张三",),"上海");
- tm.put(new Student("李四",),"深圳");
- tm.put(new Student("王五",),"苏州");
- tm.put(new Student("赵六",),"杭州");
- System.out.println(tm);
- }
- }
五、HashMap与HashTable的区别
5.1、同步性
Hashtable是同步的,这个类中的一些方法保证了Hashtable中的对象是线程安全的。而HashMap则是异步的,因此HashMap中的对象并不是线程安全的。
因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用HashMap是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销,从而提高效率。
5.2、值
HashMap可以让你将空值作为一个表的条目的key或value,但是Hashtable是不能放入空值的。HashMap最多只有一个key值为null,但可以有无数多个value值为null。
5.3、性能
HashMap的性能最好,HashTable的性能是最差(因为它是同步的)
觉得不错的点个“推荐”哦!!!
JavaSE集合(八)之Map的更多相关文章
- [javaSE] 集合框架(Map概述)
Map集合,将key对象映射到value对象 三个主要的子类:Hashtable,HashMap,TreeMap Hashtable:底层是哈希表数据结构,不允许使用null值,线程同步 HashMa ...
- JavaSE集合(十)之Map
前面给大家介绍了集合家族中的Collection家族,这一篇给大家分享的是集合中的另一个家族就是Map家族.以前的时候学习Map的时候没有很认真的去学习,我觉得很多东西还是不是很清楚. 这次我将总结的 ...
- JavaSE(八)之集合概述
前几天其实一直在学习关于linux的内容和kvm虚拟化的知识.今天有时间来回顾一下集合相关的知识,接下来我将带大家一起来回顾一起集合关联的知识. 不要辜负自己花费时间做的事情,只有用心才能得到真心的回 ...
- JavaSE(八)之Map总结
上一篇是总结了Collection接口的各种实现类,这一篇我将分享的是Map的总结,希望大家点评! 一.Map接口 1.1.为什么Collection不能满足集合的所有功能? Collection接口 ...
- Java 集合系列 15 Map总结
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Java中的集合(十一) 实现Map接口的TreeMap
Java中的集合(十一) 实现Map接口的TreeMap 一.TreeMap简介(基于JDK1.8) TreeMap是基于红黑树数据结构,是一个key-value的有序集合,该映射根据其键的自然顺序进 ...
- Java中的集合(七)双列集合顶层接口------Map接口架构
Java中的集合(七)双列集合顶层接口------Map接口 一.Map接口的简介 通过List接口,我们知道List接口下的集合是单列集合,数据存储是单列的结构.Map接口下是一个键值对(key-v ...
- javase集合 温故而知新
复习javase集合 1.为什么要有集合? 数组长度需要在初始化时确定大小,数据结构单一.因此集合出现了 2.数组和集合的区别 区别一:数组既可以存储基本数据类型,又可以存储引用类型,集合只能存储引用 ...
- Java集合框架之map
Java集合框架之map. Map的主要实现类有HashMap,LinkedHashMap,TreeMap,等等.具体可参阅API文档. 其中HashMap是无序排序. LinkedHashMap是自 ...
随机推荐
- 用js实现预览待上传的本地图片
js实现预览待上传的本地图片,代码如下: <form name="form5" id="form5" method="post" ac ...
- 【Android】5.0 第5章 常用基本控件--本章示例主界面
分类:C#.Android.VS2015: 创建日期:2016-02-06 这一章主要介绍Android简单控件的基本用法.本章源程序共有9个示例,这些示例都在同一个项目中. 项目名:ch05demo ...
- 基于Cocos2d-x学习OpenGL ES 2.0之多纹理
没想到原文出了那么多错别字,实在对不起观众了.介绍opengl es 2.0的不多.相信介绍基于Cocos2d-x学习OpenGL ES 2.0之多纹理的,我是独此一家吧.~~ 子龙山人出了一个系列: ...
- qt 例子地址
http://blog.sina.com.cn/s/articlelist_2801495241_0_2.html qt打包http://blog.chinaunix.net/uid-24641004 ...
- logback日志模板与详解
<pattern>的转换符说明: (这部分引用自http://aub.iteye.com/blog/1103685)转换符 作用 c {length } lo {length } logg ...
- c#写一个网站后台扫描器
主要分成了那么几个步骤: 1.HTTP状态码 2.字典的导入 3.显示在listview控件当中 第一步: 先来实现HTTP状态码200的判断 try { req = (HttpWebRequest) ...
- thymeleaf 的hello world
在研究一个模板引擎,选了这个thymeleaf .中间遇到很多的问题.现在在这里记录一下. 第一步:导入jar包.这里使用maven导入jar包 <!-- thymeleaf 核心包 begin ...
- dubbox-admin-2.8.4和dubbox-monitor安装
一.安装zookeeper 安装过程参照以前写的一篇博客http://www.cnblogs.com/520playboy/p/6235415.html 二.dubbox 1.准备工作下载dubbox ...
- 获取本地IP和mac等信息
1获取mac protected string getHostMacName() { string mac = ""; ManagementClass mc; mc = new M ...
- contiki list 链表
1 相关宏和数据结构 1.1 LIST_CONCAT #define LIST_CONCAT2(s1, s2) s1##s2 #define LIST_CONCAT(s1, s2) LIST_CONC ...