联系

Java中的Map类似于OC的Dictionary,都是一个个键值对组成,一键对应一值。我在之前的文章中讲解过Set,其实在JAVA底层Set依赖的也是Map,那我们都知道,Set是单列的(只有值),而Map是双列的,怎么会是Set依赖Map呢?其实做法也很简单,Set将Key隐藏,只允许访问value就实现了Set的单列效果。

功能

*a:添加功能
* V put(K key,V value):添加元素。
* 如果键是第一次存储,就直接存储元素,返回null
* 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

Map的遍历

方式一
  //通过获取所有的键来遍历值
Map<String, Integer> map = new HashMap<>();
map.put("张三", 23);
map.put("李四", 24);
map.put("王五", 25);
map.put("赵六", 26); Set<String> keySet = map.keySet(); //获取所有键的集合
Iterator<String> it = keySet.iterator(); //获取迭代器
while(it.hasNext()) { //判断集合中是否有元素
String key = it.next(); //获取每一个键
Integer value = map.get(key); //根据键获取值
System.out.println(key + "=" + value);
}

使用迭代器遍历,但是有些复杂,可以改进

方式二 (方式一改进,较简单)

这种遍历方式类似于OC中for···in语法

        //使用增强for循环遍历
for(String key : map.keySet()) { //map.keySet()是所有键的集合
System.out.println(key + "=" + map.get(key));
}
方式三 键值对对象遍历
        //Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
//获取每一个对象
Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
while(it.hasNext()) {
//获取每一个Entry对象
Map.Entry<String, Integer> en = it.next(); //父类引用指向子类对象
//Entry<String, Integer> en = it.next(); //直接获取的是子类对象
String key = en.getKey(); //根据键值对对象获取键
Integer value = en.getValue(); //根据键值对对象获取值
System.out.println(key + "=" + value);
}
方式四 (方式三改进)
        for(Entry<String, Integer> en : map.entrySet()) {
System.out.println(en.getKey() + "=" + en.getValue());
}

LinkedHashMap

LinkedHashMap可以保证怎么存就怎么取

    public static void main(String[] args) {
LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
lhm.put("张三", 23);
lhm.put("李四", 24);
lhm.put("赵六", 26);
lhm.put("王五", 25); System.out.println(lhm);
}

TreeMap

利用TreeMap可实现对键的自定义排序,同时键应为自定义类对象,同时需要在自定义类中重写compareTo方法,和hashSet里面的排序大致相同。

//按照Student的姓名排序,姓名相同按照年龄排序
public static void main(String[] args) {
//demo1();
TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() { @Override
public int compare(Student s1, Student s2) {
int num = s1.getName().compareTo(s2.getName()); //按照姓名比较
return num == 0 ? s1.getAge() - s2.getAge() : num;
}
});
tm.put(new Student("张三", 23), "北京");
tm.put(new Student("李四", 13), "上海");
tm.put(new Student("赵六", 43), "深圳");
tm.put(new Student("王五", 33), "广州"); System.out.println(tm);
}

利用HashMap统计字符串中每个字符出现的次数

核心思想就是利用HashMap的containsKey()来判断是否重复。

/**
* * A:案例演示
* 需求:统计字符串中每个字符出现的次数
*
* 分析:
* 1,定义一个需要被统计字符的字符串
* 2,将字符串转换为字符数组
* 3,定义双列集合,存储字符串中字符以及字符出现的次数
* 4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
* 5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
* 6,打印双列集合获取字符出现的次数
*/
public static void main(String[] args) {
//1,定义一个需要被统计字符的字符串
String s = "aaaabbbbbccccccccccccc";
//2,将字符串转换为字符数组
char[] arr = s.toCharArray();
//3,定义双列集合,存储字符串中字符以及字符出现的次数
HashMap<Character, Integer> hm = new HashMap<>();
//4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
for(char c: arr) {
//5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
/*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);
}
//6,打印双列集合获取字符出现的次数 for (Character key : hm.keySet()) { //hm.keySet()代表所有键的集合
System.out.println(key + "=" + hm.get(key));//hm.get(key)根据键获取值
}
}
案例演示:

集合嵌套之HashMap嵌套HashMap

需求:

一个年级有很多班,
一班定义为一个双列结合,键是学生对象,值是学生的归属地,
二班定义为一个双列结合,键是学生对象,值是学生的归属地。
无论一班二班都是班级对象,所以为了编译统一管理,把这些班级对象添加到某个年级中。

        //定义一班
HashMap<Student, String> hm88 = new HashMap<>();
hm88.put(new Student("张三", 23), "北京");
hm88.put(new Student("李四", 24), "北京");
hm88.put(new Student("王五", 25), "上海");
hm88.put(new Student("赵六", 26), "广州"); //定义二班
HashMap<Student, String> hm99 = new HashMap<>();
hm99.put(new Student("唐僧", 1023), "北京");
hm99.put(new Student("孙悟空",1024), "北京");
hm99.put(new Student("猪八戒",1025), "上海");
hm99.put(new Student("沙和尚",1026), "广州"); //定义年级
HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
hm.put(hm88, "一班");
hm.put(hm99, "二班"); //遍历双列集合
for(HashMap<Student, String> h : hm.keySet()) { //hm.keySet()代表的是双列集合中键的集合
String value = hm.get(h); //get(h)根据键对象获取值对象
//遍历键的双列集合对象
for(Student key : h.keySet()) { //h.keySet()获取集合总所有的学生键对象
String value2 = h.get(key); System.out.println(key + "=" + value2 + "=" + value);
}
}

hashMap和hashTable的区别

共同点:

底层都是哈希算法,都是双列集合

区别:
  1. HashMap是线程不安全的,效率高,JDK1.2版本,Hashtable是线程安全的,效率低,JDK1.0版本的
  2. HashMap可以存储null键和null值,Hashtable不可以存储null键和null值

深入了解Map的更多相关文章

  1. mapreduce中一个map多个输入路径

    package duogemap; import java.io.IOException; import java.util.ArrayList; import java.util.List; imp ...

  2. .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法

    .NET Core中间件的注册和管道的构建(3) ---- 使用Map/MapWhen扩展方法 0x00 为什么需要Map(MapWhen)扩展 如果业务逻辑比较简单的话,一条主管道就够了,确实用不到 ...

  3. Java基础Map接口+Collections工具类

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  4. Java基础Map接口+Collections

    1.Map中我们主要讲两个接口 HashMap  与   LinkedHashMap (1)其中LinkedHashMap是有序的  怎么存怎么取出来 我们讲一下Map的增删改查功能: /* * Ma ...

  5. 多用多学之Java中的Set,List,Map

            很长时间以来一直代码中用的比较多的数据列表主要是List,而且都是ArrayList,感觉有这个玩意就够了.ArrayList是用于实现动态数组的包装工具类,这样写代码的时候就可以拉进 ...

  6. Java版本:识别Json字符串并分隔成Map集合

    前言: 最近又看了点Java的知识,于是想着把CYQ.Data V5迁移到Java版本. 过程发现坑很多,理论上看大部分很相似,实践上代码写起来发现大部分都要重新思考方案. 遇到的C#转Java的一些 ...

  7. MapReduce剖析笔记之八: Map输出数据的处理类MapOutputBuffer分析

    在上一节我们分析了Child子进程启动,处理Map.Reduce任务的主要过程,但对于一些细节没有分析,这一节主要对MapOutputBuffer这个关键类进行分析. MapOutputBuffer顾 ...

  8. MapReduce剖析笔记之七:Child子进程处理Map和Reduce任务的主要流程

    在上一节我们分析了TaskTracker如何对JobTracker分配过来的任务进行初始化,并创建各类JVM启动所需的信息,最终创建JVM的整个过程,本节我们继续来看,JVM启动后,执行的是Child ...

  9. MapReduce剖析笔记之五:Map与Reduce任务分配过程

    在上一节分析了TaskTracker和JobTracker之间通过周期的心跳消息获取任务分配结果的过程.中间留了一个问题,就是任务到底是怎么分配的.任务的分配自然是由JobTracker做出来的,具体 ...

  10. MapReduce剖析笔记之三:Job的Map/Reduce Task初始化

    上一节分析了Job由JobClient提交到JobTracker的流程,利用RPC机制,JobTracker接收到Job ID和Job所在HDFS的目录,够早了JobInProgress对象,丢入队列 ...

随机推荐

  1. 1.QT中播放视频,录音程序的编写

     1  通过process的方式播放视频 T22VideoPlayer.pro HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gu ...

  2. Cocos2D iOS之旅:如何写一个敲地鼠游戏(三):素材最终解决方法

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  3. 07_NoSQL数据库之Redis数据库:Redis的高级应用之事务处理、持久化操作、pub_sub、虚拟内存

     事务处理 Redis对事务的支持目前还比较简单.Redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令.当一个client在一个连接中发出mul ...

  4. 学习笔记3-开发与运行(卸载)第一个ANDROID应用

    新建Android项目 1.      配置好Android坏境以后,新建项目选择Android Project. 2.      选择针对哪个平台开发的应用(Android2/Android4等) ...

  5. 如何在Cocos2D游戏中实现A*寻路算法(三)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交流 ...

  6. 《java入门第一季》之泛型方法和泛型接口

    一.泛型方法. /* * 泛型方法:把泛型定义在方法上.格式:public <泛型类型> 返回类型 方法名(泛型类型 t) public <T> void show(T t){ ...

  7. R12中注册客户化应用为多组织应用

    Oralce EBS R12中引入了MOAC的控制,所有多OU的表对象都添加了数据库VPD的控制策略,需要访问这些对象中的数据,首先需要进行多组织环境的初始化,但是如果客户化的应用中也需要具备多OU的 ...

  8. 学习tornado:异步

    why asynchronous tornado是一个异步web framework,说是异步,是因为tornado server与client的网络交互是异步的,底层基于io event loop. ...

  9. Java异常处理示例

    翻译人员: 铁锚 翻译日期: 2013年11月22日 原文链接: Java Exception Handling Example 本文中有两个示例, 第一个演示了所有调用其他方法的地方,都必须处理被调 ...

  10. Android ViewManager解读之requestLayout() 详解

    尊重原创: http://blog.csdn.net/sk719887916/article/details/48464035 上篇<Android View 中invalidate() 你所不 ...