前面给大家介绍了集合家族中的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的更多相关文章

  1. Java中的集合(十四) Map的实现类LinkedHashMap

    Java中的集合(十四) Map的实现类LinkedHashMap 一.LinkedHashMap的简介 LinkedHashMap是Map接口的实现类,继承了HashMap,它通过重写父类相关的方法 ...

  2. [javaSE] 集合框架(Map概述)

    Map集合,将key对象映射到value对象 三个主要的子类:Hashtable,HashMap,TreeMap Hashtable:底层是哈希表数据结构,不允许使用null值,线程同步 HashMa ...

  3. JavaSE集合(八)之Map

    前面给大家介绍了集合家族中的Collection家族,这一篇给大家分享的是集合中的另一个家族就是Map家族.以前的时候学习Map的时候没有很认真的去学习,我觉得很多东西还是不是很清楚. 这次我将总结的 ...

  4. Java中的集合(十二) 实现Map接口的WeakHashMap

    Java中的集合(十二) 实现Map接口的WeakHashMap 一.WeakHashMap简介 WeakHashMap和HashMap一样,WeakHashMap也是一个哈希表,存储的也是键值对(k ...

  5. JavaSE(十)之Map总结

    上一篇是总结了Collection接口的各种实现类,这一篇我将分享的是Map的总结,希望大家点评! 一.Map接口 1.1.为什么Collection不能满足集合的所有功能? Collection接口 ...

  6. java 集合框架(十六)Map

    一.概述 Map是一个包含键值对的集合,一个map不能有重复的键(key),而且每个键至多只能对应一个值.Map同Collection一样,它的所有通用实现都会提供一个转换器构造函数,接收一个Map类 ...

  7. JavaSE(十)之Map总结 (转)

    http://www.cnblogs.com/zhangyinhua/p/7545979.html 阅读目录(Content) 一.Map接口 1.1.为什么Collection不能满足集合的所有功能 ...

  8. Java中的集合(十三) 实现Map接口的Hashtable

    Java中的集合(十三) 实现Map接口的Hashtable 一.Hashtable简介 和HashMap一样,Hashtable采用“拉链法”实现一个哈希表,它存储的内容是键值对(key-value ...

  9. javase集合 温故而知新

    复习javase集合 1.为什么要有集合? 数组长度需要在初始化时确定大小,数据结构单一.因此集合出现了 2.数组和集合的区别 区别一:数组既可以存储基本数据类型,又可以存储引用类型,集合只能存储引用 ...

随机推荐

  1. 设计模式之桥接模式(Bridge模式)

    我想大家小时候都有用蜡笔画画的经历吧.红红绿绿的蜡笔一大盒,根据想象描绘出格式图样.而毛笔下的国画更是工笔写意,各展风采.而今天我们的故事从蜡笔与毛笔说起. 设想要绘制一幅图画,蓝天.白云.绿树.小鸟 ...

  2. C#和NewSQL更配 —— TiDB入门(可能是C#下的全网首发)

    阅读目录 背景 TiDB是什么 环境部署 实战 性能测试 结语 一.背景 在上一篇尝试CockroachDB(传送门在此:http://www.cnblogs.com/Zachary-Fan/p/co ...

  3. SpringMVC(三)-- 视图和视图解析器、数据格式化标签、数据类型转换、SpringMVC处理JSON数据、文件上传

    1.视图和视图解析器 请求处理方法执行完成后,最终返回一个 ModelAndView 对象 对于那些返回 String,View 或 ModeMap 等类型的处理方法,SpringMVC 也会在内部将 ...

  4. JVM内存结构和6大区域

    摘自 http://www.iteye.com/news/30350 对于我们一般理解的计算机内存,它算是CPU与计算机打交道最频繁的区域,所有数据都是先经过硬盘至内存,然后由CPU再从内存中获取数据 ...

  5. 解决MVC模式文件下载附件中文名称乱码

    解决如下: 进行url编码:Server.UrlPathEncode(file.AttachmentName) return File(file.TempWorkPath, CommonTools.G ...

  6. RAISERROR

    RAISERROR 可以抛出一个错误,并被程序捕获,在存储过程经常使用: 是否进入Catch代码执行区域,在于错误严重等级设置 RAISERROR ('无效数据', 11 , 1) 第一个参数:自定义 ...

  7. django源码解析一(请求处理流程)

    1.我们都知道WSGI是一个规范,规范了server和application之间通信的一些约束,server端在监听到请求之后,会把请求转给application去处理,他们之间关联起来的桥梁是一个e ...

  8. poj 3635 带花费的Dij+head优化

    练习!! 这里主要需要注意的是进队的条件和dp[][]状态的控制,dp[i][j]表示到第i个城市剩余汽油为j的最小花费. 代码: #include<iostream> #include& ...

  9. 猎八哥FLY——将数据库中的某一表中的某一列或者多列添加到另一张表的某一列中

    成绩表的字段:xueshenghao,yu,shu,yy均为int类型.新标与成绩表字段相同,不同的是成绩表中拥有数据,而新表中没有(是一张空表,一条数据都没有).需求:将成绩表中每一个人的yu,sh ...

  10. WPF的TextBox水印效果详解

    一种自以为是的方式: 本来只是想简单的做个水印效果,在文本框内容为空的时候提示用户输入,这种需求挺常见.网上一搜 都是丢给你你一大段xaml代码.用c#代码实现我是不倾向了 既然用wpf就得Xaml啊 ...