在Java中,Set的底层事实上是基于Map实现的,Map内部封装了一个Entry内部接口,由实现类来封装key-value对,当value值均为null时,key的集合就形成了Set。因此,Map集合具有如下的一些特点:

1. Key集因为是Set的实现,因此是无顺序、不可重复的。

2. Value集是List的实现,因此是可以重复的,每个元素根据key来索引。

3. Map内部包含一个Entry内部接口,用于定义key-value对,由实现类来对外提供查找和设置value的方法。

Map的基本功能如下:

 public class TestMapBasic {

     public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
//添加键值对,value可重复
map.put("AAA", 110);
map.put("BBB", 120);
map.put("CCC", 20);
map.put("DDD", 120);
//添加重复key的时候,value会覆盖旧值,方法返回旧值
System.out.println(map.put("CCC", 111));
System.out.println(map);
//通过key和value查找是否存在对应的键\值
System.out.println("map.containsKey(\"BBB\")?: " + map.containsKey("BBB"));
System.out.println("map.containsValue(110)?: " + map.containsValue(110));
//遍历Map的增强for循环
for(String key:map.keySet()) {
System.out.println(key + "-->" + map.get(key));
}
//根据key删除value
map.remove("AAA");
System.out.println(map);
}
}

Map的Java8增强方法示例如下:

 public class TestMapAdvance {

     public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
//添加键值对,value可重复
map.put("AAA", 110);
map.put("BBB", 120);
map.put("CCC", 20);
map.put("DDD", 120);
//因为map中无ZZZ,因此替换失败
map.replace("ZZZ", 122);
System.out.println(map);
//使用原value与参入参数重新计算value
map.merge("CCC", 20, (oldVal, param) -> (oldVal+param)*2);
System.out.println(map);
//当key为Java,对应的value不存在或null, 计算结果为新value
map.computeIfAbsent("Java", (key) -> key.length());
System.out.println(map);
//当key为Java存在, 则用新结果替换
map.computeIfPresent("Java", (key, value) -> value * 100);
System.out.println(map);
}
}

HashMap和Hashtable

HashMap和Hashtable都是Map接口的典型实现类,两者的区别在于:

1. HashMap是线程不安全的,性能较高,可以使用null作为key或者value

2. Hashtable是线程安全的,不可以用null做key和value。

与HashSet一样,HashMap和Hashtable不能保证key-value对的顺序,判断两个元素是否相等的标准为:

1. 两个key的equals方法比较返回true

2. 两个key的HashCode方法值相同

HashMap和Hashtable的containsValue()方法,用于判断是否包含指定的value,判断标准为两个value的equals方法相等即可。因此:

1. 使用自定义类作为Key时,如果重写equals和HashCode方法,需确保判断标准一致。

2. 尽量不要使用可变对象作为Key,如果确实需要则不要在程序中修改可变对象。

LinkedHashMap

LinkedHashMap在底层使用双链表来维护键值对的顺序,因而性能略低于HashMap,但在迭代集合元素时有较好的性能。

Properties

Properties是Hashtable的子类,相当于一个key和value都是String的Map。使用Properties可以方便地把属性文件的“属性名=属性值”转化为Map的键值对,还可以实现Map的键值对与XML文件之间的相互转化,广泛用于JDBC等应用场景中。

 public class TestProperties {

     public static void main(String[] args) throws FileNotFoundException, IOException {
Properties props = new Properties();
//为Properties对象添加元素
props.setProperty("username", "admin");
props.setProperty("password", "123456");
//写入文件
props.store(new FileOutputStream("test.properties"), "comment line");
Properties props2 = new Properties();
props2.setProperty("gender", "male");
//将文件中的内容追加到Props2的元素中
props2.load(new FileInputStream("test.properties"));
System.out.println(props2);
} }

TreeMap

TreeMap是SortedMap接口的实现类,同时也是TreeSet类的底层实现模型。因此具有与TreeSet相似的性质:

1. TreeMap底层由红黑树的数据结构所实现,每个键值对即为红黑树的一个节点。TreeMap存储键值对时,需要根据Key对节点进行排序。

2. TreeMap的排序方式包括两种:

2.1 自然排序:通过Key所实现的Comparable接口来实现,要求Key都是同一个类的对象

2.2 定制排序:创建TreeMap时,传入一个Comparator对象,负责对Key元素进行排序。

3. 如果使用自定义类作为Key,重写该类的equals方法和compareTo方法应该一致:equals方法返回true时,compareTo方法要返回0。

与HashSet相似,HashMap因为存储的键值对是有序的,因此提供了访问第一个、前一个、第一个、最后一个键值对的方法,以及若干截取子TreeMap的方法。

 class R implements Comparable<Object>{

     int count;

     public R(int count) {
super();
this.count = count;
} @Override
public String toString() {
return "R [count=" + count + "]";
} @Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
R other = (R) obj;
if (count != other.count)
return false;
return true;
} @Override
public int compareTo(Object o) {
R r = (R)o;
return count > r.count ? 1: count < r.count ? -1 : 0;
}
} public class TestTreeMap { public static void main(String[] args) {
TreeMap<R, String> tm = new TreeMap<>();
tm.put(new R(3), "AAAA");
tm.put(new R(-5), "BBB");
tm.put(new R(9), "CCCCCC");
System.out.println(tm);
//返回第一个Entry对象
System.out.println(tm.firstEntry());
//返回最后一个Key
System.out.println(tm.lastKey());
//返回比R(2)大一个的Key
System.out.println(tm.higherKey(new R(2)));
//返回比R(2)小的一个Key
System.out.println(tm.lowerKey(new R(2)));
//获取子串
System.out.println(tm.subMap(new R(-1), new R(4)));
System.out.println(tm);
}
}

WeakHashMap

WeakHashMap与HashMap的用法基本相似,区别在于:

1. HashMap的Key保留的是对实际对象的强引用,只要HashMap对象不销毁,所有Key引用对象就不会被垃圾回收;HashMap也不会自动删除这些Key的键值对。

2. WeakHashMap的Key保留的是对实际对象的弱引用,意味着如果这些Key没有被其它强引用对象所引用,Key对象可能会被垃圾回收;WeakHashMap对象也可能会删除这些键值对。

 public class TestWeakHashMap {

     public static void main(String[] args) {
WeakHashMap<String, String> whm = new WeakHashMap<>();
//添加的三个Key对象都是弱引用的匿名类对象
whm.put(new String("Python"), new String("pass"));
whm.put(new String("R"), new String("good"));
whm.put(new String("Scala"), new String("great"));
//添加一个系统缓存的字符串直接量, 为强引用对象,作为Key
whm.put("Java", new String("Number One"));
System.out.println(whm);
//通知系统进行垃圾回收
System.gc();
System.runFinalization();
//此时whm仅保留一个强引用的Java键值对
System.out.println(whm);
}
}

IdentityHashMap

IdentityHashMap与HashMap的基本性质和用法大致相同,如可以添加null元素,存储元素的无序性等。核心区别在于判断两个Key对象的标准:

IdentityHashMap严格要求两个Key必须是Key1 == Key2的严格相等,即堆内存地址相同。

 public class TestIdentityHashMap {

     public static void main(String[] args) {
IdentityHashMap<String, Integer> ihm = new IdentityHashMap<>();
//两个new String对象,会被认为是不同的Key,一起添加到集合中
ihm.put(new String("Python"), 100);
ihm.put(new String("Python"), 98);
//字符串直接量Java的内存地址相同,会被认为是同一个对象, 因此只会添加一个(覆盖前值)
ihm.put("Java", 100);
ihm.put("Java", 11);
System.out.println(ihm);
}
}

总结

一般的使用中,为了获取较方便的快速查询,使用HashMap较多。特别地,如果需要一个总是排好序的Key-Value集合,则考虑TreeMap。通过TreeMap的KeySet可以直接获取Key集合,然后通过Arrays的工具类转为数组,就可以通过二分法快速查找已经排序完成的对象。

Java容器深入浅出之Map、HashMap、Hashtable及其它实现类的更多相关文章

  1. Java基础系列 - JAVA集合ArrayList,Vector,HashMap,HashTable等使用

    package com.test4; import java.util.*; /** * JAVA集合ArrayList,Vector,HashMap,HashTable等使用 */ public c ...

  2. Collections+Iterator 接口 | Map+HashMap+HashTable+TreeMap |

    Collections+Iterator 接口 1. Collections 是一个操作 Set.List 和 Map 等集合的工具类 Collections 中提供了大量方法对集合元素进行排序.查询 ...

  3. Java 容器(list, set, map)

    java容器类库的简化图: (虚线框表示接口, 实线框表示普通的类, 空心箭头表示特定的类实现了接口, 实心箭头表示某个类可以生成箭头所指的类对象) 继承Collection的主要有Set 和 Lis ...

  4. [Java集合] 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联.

    注: 今天看到的一篇讲hashMap,hashTable,concurrentHashMap很透彻的一篇文章, 感谢原作者的分享. 原文地址: http://blog.csdn.net/zhanger ...

  5. Java中ArrayList,Vector,LinkedList,HashMap,HashTable,HashSet对比及总结

    1.所有的集合的父类都是Collection的接口 2.Set List Map 区别 A  在Set里面:无法添加元素的顺序,所以Set里面的元素不能重复 B  在List中:有索引号,类似于数组, ...

  6. Java容器解析系列(11) HashMap 详解

    本篇我们来介绍一个最常用的Map结构--HashMap 关于HashMap,关于其基本原理,网上对其进行讲解的博客非常多,且很多都写的比较好,所以.... 这里直接贴上地址: 关于hash算法: Ha ...

  7. Java容器深入浅出之Collection与Iterator接口

    Java中用于保存对象的容器,除了数组,就是Collection和Map接口下的容器实现类了,包括用于迭代容器中对象的Iterator接口,构成了Java数据结构主体的集合体系.其中包括: 1. Co ...

  8. Java容器深入浅出之HashSet、TreeSet和EnumSet

    Java集合中的Set接口,定义的是一类无顺序的.不可重复的对象集合.如果尝试添加相同的元素,add()方法会返回false,同时添加失败.Set接口包括3个主要的实现类:HashSet.TreeSe ...

  9. Java容器深入浅出之数组

    写在前面 关于Java的学习,特别是对于非计算机专业的同学来说,我总是主张从实践中来,到实践中去的学习方法.Java本身是一门应用性特别强的高级编程语言,因此如果能在基于实际开发的经验基础上,对Jav ...

随机推荐

  1. NGUI可展开列表的实现

    本文来自网易云社区 作者:汪毅军 最近使用了NGUI做了下可展开列表,其主要思路如下:首先最外层使用Scroll view以达到滑动效果,然后列表使用UITable进行排列,最后通过点击Item控制I ...

  2. 一键将 Python2 代码自动转化为 Python3

    问题 Python2 的代码直接在 Python3 环境运行的话会报错误: 如果大量的代码,无论是批量替换,还是逐行修改都够累的,这活儿表示不能干! 有没有办法一键转换呢? 百度了一下发现网上的方法如 ...

  3. android 判断应用是否在前台显示

    在一些场景下我们需要知道应用是否在前台显示,当不在前台显示的时候,一些后台进程可以暂时停止,比如一些查询任务.不必要的线程.不需要的渲染等,以减少对设备资源的占用.判断应用是否在前台通常可以使用一下方 ...

  4. Installshield相关的后续操作<一>图解

    1.XML文件读取 选择需要读取XML文件 2.SQL数据库的安装 这里选择的文件是数据库脚本.如果脚本没有创建数据库的语句,还需手动输入. 3.自定义界面Dialogs 下一步: 上面红色框框里面是 ...

  5. Unity优化方向——优化Unity游戏中的脚本(译)

    原文地址:https://unity3d.com/cn/learn/tutorials/topics/performance-optimization/optimizing-scripts-unity ...

  6. 0.前言 three.js 简介

    前言 前段时间开始接触three.js本来以为会很简单但是真正开始学习的时候才发现事情并不是我想象的那么容易,three.js的学习资料非常的少稍微好一点的资料就是收费的,给three.js的学习带来 ...

  7. web.xml配置文件中<async-supported>true</async-supported>报错

    web.xml配置文件中<async-supported>true</async-supported>报错 http://blog.csdn.net/dream_ll/arti ...

  8. “Hello World!团队”Final发布—视频链接+文案+美工

    视频发布:http://www.bilibili.com/video/av17022373/ 文案加美工:http://www.cnblogs.com/chjy/p/7990116.html SkyH ...

  9. Daily Scrum (2015/11/3)

    今天我们的爬虫能在pc上成功运行并且把所爬取的数据存到服务器上了!我们已经搭建好数据库,把相关信息存到数据库中,并把数据存到D盘里共享给数据处理小组使用. 成员 今日工作 时间 明日工作 符美潇 完成 ...

  10. 20172301 2017-2018-2 《程序设计与数据结构》实验一《Java开发环境的熟悉》实验报告

    20172301 2017-2018-2 <程序设计与数据结构>实验一<Java开发环境的熟悉>实验报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 郭 ...