Map接口作为Java集合框架中的第二类接口,其子接口为SortedMap接口,SortedMap接口的子接口为NavigableMap接口。

  实现了Map接口具体类有:HashMap(子类LinkedHashMap)、TreeMap、EnumMap、WeakHashMap、IdentityHashMap。

  1.HashMap

  HashMap类实现了Map接口,由HashMap类实现的Map集合,允许以null作为键对象,但是因为键对象不可以重复,所以这样的键对象只能有一个。

  如果经常需要添加、删除和定位映射关系,建议利用HashMap类实现Map集合,不过在遍历集合时,得到的映射关系是无序的。

  ☆在使用由HashMap类实现的Map集合时,需要重写作为主键对象类的HashCode方法。在重写hashCode方法时,有两条基本原则:

  • 不唯一原则:不必为每个对象生成一个唯一的哈希码,只要通过hashCode方法生成的哈希码能够利用get方法得到利用put方法添加的映射关系即可。
  • 分散原则:生成哈希码的算法应尽量使哈希码的值分散一些,不要很多哈希码值都集中在一个范围内,这样有利于提高由HashMap类实现的Map集合的性能。

  在使用由HashMap类实现的Map集合时,也需要重写作为主键对象类的equals方法,该方法默认比较两个对象的地址,即使这两个键对象的内容完全相同,也不认为是同一个对象。

  (1)新建一个Map集合对象

Map<PK_person, Person> map = new HashMap<>();

  (2)使用Map类的put方法添加一个键/值对象

        PK_person pk_person = new PK_person();
pk_person.setPrefix("MR");
pk_person.setNumber(13211041);
map.put(pk_person, new Person("小一", pk_person));

  (3)使用Map类的get方法通过键得到值对象

        Person person = map.get(pk_person);
System.out.println(person.getName() + " " + person.getNumber().getPK());

  (4)新建一个副本键对象,内容和前面的键对象完全一致,这里会打印“该键对象不存在”,这是因为虽然pk_person2和pk_person的内容完全一样,但是系统默认的equals方法比较的是两个对象的地址,而这两个对象的地址不一致,所以不认为是同一个对象。

        PK_person pk_person2 = new PK_person();
pk_person2.setPrefix("MR");
pk_person2.setNumber(13211041); Person person2 = map.get(pk_person2);
if (person2==null) {
System.out.println("该键对象不存在");
} else {
System.out.println(person2.getNumber().getPK());
}

  (5)根据实际需求,如果两个键对象的内容完全一样,那么我们就应该认为这两个键对象一样,通过get方法应该能够得到映射的值对象,这个时候可以通过在键对象的类PK_person中重写hashCode方法和equals方法来解决。

  这里将默认的hashCode方法重写,从而保证了只要是键对象的内容相等,它们的hashCode码就相等。

  通过equals方法比较pk_person2和pk_person时,首先不是同一个实例、obj也不为空、是同一个类的实例,同时哈希码相等,于是判断出这两个键对象是相等的。

    // 重写hashCode方法,返回的哈希码就是简单的int类型的number加上String类型的prefix对象的hashCode方法
@Override
public int hashCode() {
return number + prefix.hashCode();
} // 重写equals方法
@Override
public boolean equals(Object obj) {
if (this == obj) // 是否为同一个实例
return true;
if (obj == null) // 是否null
return false;
if (getClass() != obj.getClass()) // 是否为同一个类的实例
return false; final PK_person other = (PK_person) obj; // 对应的哈希码是否相同
if (this.hashCode()!=other.hashCode())
return false;
return true;
}

  然后再次运行上述程序,就可以得到对应的结果:

MR_13211041

  完整代码:

package hashMap.jun.iplab;

public class PK_person {

    private String prefix;
private int number; public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
} public String getPK() {
return this.prefix + "_" + this.number;
} public void setPK(String pk) {
int i = pk.indexOf("_");
this.prefix = pk.substring(0, i);
this.number = new Integer(pk.substring(i));
} // 重写hashCode方法,返回的哈希码就是简单的int类型的number加上String类型的prefix对象的hashCode方法
@Override
public int hashCode() {
return number + prefix.hashCode();
} // 重写equals方法
@Override
public boolean equals(Object obj) {
if (this == obj) // 是否为同一个实例
return true;
if (obj == null) // 是否null
return false;
if (getClass() != obj.getClass()) // 是否为同一个类的实例
return false; final PK_person other = (PK_person) obj; // 对应的哈希码是否相同
if (this.hashCode()!=other.hashCode())
return false;
return true;
} }

PK_person

package hashMap.jun.iplab;

public class Person {

    private String name;
private PK_person number; public Person(String name, PK_person number) {
super();
this.name = name;
this.number = number;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public PK_person getNumber() {
return number;
} public void setNumber(PK_person number) {
this.number = number;
} }

Person

package hashMap.jun.iplab;

import java.util.HashMap;
import java.util.Map; public class Test { public static void main(String[] args) { Map<PK_person, Person> map = new HashMap<>(); PK_person pk_person = new PK_person();
pk_person.setPrefix("MR");
pk_person.setNumber(13211041);
map.put(pk_person, new Person("小一", pk_person));
// Person person = map.get(pk_person);
// System.out.println(person.getName() + " " + person.getNumber().getPK());
PK_person pk_person2 = new PK_person();
pk_person2.setPrefix("MR");
pk_person2.setNumber(13211041);
Person person2 = map.get(pk_person2);
if (person2==null) {
System.out.println("该键对象不存在");
} else {
System.out.println(person2.getNumber().getPK());
} }
}

Test

  2.TreeMap类

  TreeMap类不仅实现了Map接口,还实现了Map接口的子接口SortedMap接口。

  由TreeMap类实现的Map集合,不允许键对象为null,因为集合中的映射关系是根据键对象按照一定顺序排列的。

  在添加、删除和定位映射关系上,TreeMap类要比HashMap类的性能差一些,但是其中的映射关系具有一定的顺序,如果不需要一个有序的集合,则建议使用HashMap类;如果需要进行有序的遍历输出,则建议使用TreeMap类。

  通常的做法是:首先利用HashMap类实现一个Map集合并初始化,将元素添加到Map集合中,然后再利用TreeMap类实现一个TreeMap集合,在将原来的Map集合中的元素都添加到新的TreeMap集合中,在根据要求进行升序或者降序即可。

  TreeMap由于实现了SortedMap接口而拥有的方法为:

  

  (1)由HashMap类实现一个Map集合并将元素添加到Map集合中

        Person person1 = new Person("小一", 13311123);
Person person2 = new Person("小二", 13223131);
Person person3 = new Person("小三", 13432412);
Person person4 = new Person("小四", 13621312);
Person person5 = new Person("小五", 13531231); Map<Number, Person> map = new HashMap<>();
map.put(person1.getId_card(), person1);
map.put(person2.getId_card(), person2);
map.put(person3.getId_card(), person3);
map.put(person4.getId_card(), person4);
map.put(person5.getId_card(), person5);

  通过遍历查看此时Map集合中的元素的排列顺序,此时没有顺序:

        Iterator<Number> it = map.keySet().iterator();
while (it.hasNext()) {
Number number = (Number) it.next();
System.out.println(number);
} 输出:
13432412
13531231
13223131
13311123
13621312

  (2)创建一个TreeMap对象,然后将原来的map集合中的数据都添加到新建的treeMap集合中,然后使用默认的排序方式即键对象的升序(Person类实现了Comparator接口)顺序进行访问

        TreeMap<Number, Person> treeMap = new TreeMap<>();
treeMap.putAll(map);
Iterator<Number> it_1 = treeMap.keySet().iterator();
while (it_1.hasNext()) {
Number number = (Number) it_1.next();
System.out.println(number);
} 输出:
13223131
13311123
13432412
13531231
13621312

  (3)新创建一个TreeMap对象,然后将原来的map集合中的数据都添加到新建的treeMap集合中,然后按照降序即反转顺序排序进行访问:

        TreeMap<Number, Person> treeMap = new TreeMap<>(Collections.reverseOrder());
treeMap.putAll(map);
Iterator<Number> it_1 = treeMap.keySet().iterator();
while (it_1.hasNext()) {
Number number = (Number) it_1.next();
System.out.println(number);
}
输出:
13621312
13531231
13432412
13311123
13223131

Java基础(二十三)集合(6)Map集合的更多相关文章

  1. Java基础操作面试题:Map集合排序 需要TreeMap 构造方法参数有比较器 输入字符串,统计A、B、C、D、出现次数,由高到低输出字母和出现次数,使用Map集合完成此题

    Map和Collections是同级别的,不能像List排序那样直接用Collections.sort(new Comparator<?>(){ 复写compara方法}); HashMa ...

  2. java基础-IO流对象之Properties集合

    java基础-IO流对象之Properties集合 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Properties集合的特点 Properties类表示了一个持久的属性集. ...

  3. java集合(List集合与Map集合的数据转换)

    List集合与Map集合的数据转换 实现List和Map数据的转换. 具体要求如下: 功能1:定义方法public void listToMap( ){ }将List中Student元素封装到Map中 ...

  4. Java常用的几种集合, Map集合,Set集合,List集合

    Java中  Object是所有类的根 Java集合常用的集合List集合.Set集合.Map集合 Map接口常用的一些方法 size() 获取集合中名值对的数量 put(key k, value v ...

  5. java学习笔记—集合之Map集合

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; text-align: center; font: 12.0px Times } p.p2 { margin: 0.0p ...

  6. 红黑树规则,TreeSet原理,HashSet特点,什么是哈希值,HashSet底层原理,Map集合特点,Map集合遍历方法

    ==学习目标== 1.能够了解红黑树 2.能够掌握HashSet集合的特点以及使用(特点以及使用,哈希表数据结构) 3.能够掌握Map集合的特点以及使用(特点,常见方法,Map集合的遍历) 4.能够掌 ...

  7. Java面试题总结之Java基础(二)

    Java面试题总结之Java基础(二) 1.写clone()方法时,通常都有一行代码,是什么? 答:super.clone(),他负责产生正确大小的空间,并逐位复制. 2.GC 是什么? 为什么要有G ...

  8. Bootstrap <基础二十三>页面标题(Page Header)

    页面标题(Page Header)是个不错的功能,它会在网页标题四周添加适当的间距.当一个网页中有多个标题且每个标题之间需要添加一定的间距时,页面标题这个功能就显得特别有用.如需使用页面标题(Page ...

  9. Java入土--Java基础(二)

    Java基础(二) 接上一讲,我们接着来聊聊Java的一些基础知识,下一讲就会进行流程的控制. 类型转换 首先呢,是类型的转换,接上一个内容的数据类型,类型转换就是数据类型更进一步的应用. 由于Jav ...

  10. Java笔记(二十三)……Map集合

    Map接口 Map<K,V> 该集合存储的是键值对,成对往集合里存,而且要保证键的唯一性 常用方法 添加 Vput(K key, V value) voidputAll(Map<? ...

随机推荐

  1. FTP无法登录问题-内有网盘福利

    http://dinghuqiang.blog.51cto.com/19871/701185/ 一顿操作猛如虎,还是没解决. 然后我想想,会不会是浏览器缓存问题? 换个火狐登录看看! 哇擦!看到报错了 ...

  2. JIRA集成GitHub

    原因: 作为管理员, 为用户提高效率的角度,配置测试此服务.让用户从JIRA内看到代码分支,提交信息,pull requests等等, 让Github的代码提交记录和JIRA的任务管理系统集成在一起, ...

  3. Java入门系列之hashCode和equals(十二)

    前言 前面两节内容我们详细讲解了Hashtable算法和源码分析,针对散列函数始终逃脱不掉hashCode的计算,本节我们将详细分析hashCode和equals,同时您将会看到本节内容是从<E ...

  4. layDate——初步使用

    layui系列中layDate的使用教程网址 https://www.layui.com/laydate/ 我这里简单举例: 1.引入js <script type="text/jav ...

  5. 蓝松SDK支持以下的AE特性

    蓝松短视频SDK 支持Ae模板, 您可以在PC端用AE设计好模板,然后导入到SDK中, 蓝松SDK支持一下的AE特性:1, Ae中的图片图层,任意多个图片图层, 每个图片的移动旋转缩放透明,锚点,蒙版 ...

  6. 在github上部署第二个repository

    想在github上保存一些平时写的测试程序,所以就建立了一个repository:https://github.com/commshare/testProgram 建立好之后,怎么把本地的代码上传呢. ...

  7. 如何将腾讯视频的qlv格式转换为mp4格式

    基本上每个视频app都会有自己固有的视频播放格式,比如优酷的KUX.爱奇艺的QSV和腾讯的QLV等.而今天我们重点介绍腾讯的QLV格式如何转换为MP4格式,小便也是经过多次的摸索多次的软件试用,发现的 ...

  8. 究竟是.NET淹没在汪洋大海,还是人心的浮躁、见识的短浅?

    这些年来有相当多的.net开发者转了其他语言,也有一部分是迫不得已因为公司的转型而转,其中也有一大部分觉得.net没前途性能不好比某些语言性能差.还有一部分会说出一些名词去指责.net说他做不到,其实 ...

  9. 《完美解决系列》Android5.0以上 Implicit intents with startService are not safe

    在Android6.0上,使用了以下代码: Intent intent = new Intent(); intent.setAction("xxx.server"); bindSe ...

  10. 低效sql语句执行缓慢引起的大量占用服务器的CPU问题处理 (优化心得)

    1> 2> 3> 4> 5>删除不良的执行计划后执行时间仍然有150s,这实在是太慢了,继续查看原sql代码,发现父表的关联条件放在了子查询里,这是应该避免的 调整原sq ...