在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. jstl c:if 不能判断成功的问题

    这是因为test里不能直接用 ${value}=='字符串' 的方式来进行判断比较,所以只能这样写 ${value == '字符串'} ,这样就能判断了

  2. centos6.5部署gitlab

    安装过程参考: https://www.cnblogs.com/wenwei-blog/p/5861450.html https://ehlxr.me/2016/07/31/CentOS-%E7%B3 ...

  3. idea 和 WebStorm 配置 http代理 并更换主题

    proxy,http,socks5 当前 idea 主题为:(idea 自带) idea 编辑器的主题颜色字体为:(网上下载的 jar 包) 因为今天在安装下面这个主题时需要在 idea的 plugi ...

  4. x5webview 自定义全屏界面

    集成X5WEBVIEW可以选择全屏模式为标准全屏还是x5全屏,而不设置默认为false. 首先看看标准全屏的基本设置, if (webView.getX5WebViewExtension() != n ...

  5. allure2 report+ jenkins 使用

    物色了一个挺漂亮的报告生成插件 ——allure. 下面介绍一下这个报告的使用. 1. 添加依赖 <dependencies> <!-- https://mvnrepository. ...

  6. 【SIKIA计划】_11_Unity动画插件-DOTween笔记

    [插值移动]using DG.Tweening;public class GetStart:MomoBehaviour{ public Vector3 myValue = new Vector3(0, ...

  7. CHAPTER 24 History of Our Planet 第24章 我们行星的历史

    CHAPTER 24 History of Our Planet 第24章 我们行星的历史 Uncovering the bones of ancient beasts is only part of ...

  8. 虚拟机中安装MAC OS X教程(适用所有电脑方法,特别是cpu不支持硬件虚拟化的电脑)

    前言 之前写了一篇在Windows上搭建Object-C开发环境,并且写了一个HelloWorld程序.但真正开发苹果软件是在MAC OS X系统中(以下简称OSX)中.买不起MacBook,也没有O ...

  9. 从零开始的Python学习 知识补充sorted

    sorted()方法 sorted()可用于任何一个可迭代对象. 原型为sorted(iterable, cmp=None, key=None, reverse=False) iterable:一个可 ...

  10. BOM 头是什么,怎么除去

    WINDOWS自带的记事本,在保存一个以 UTF-8 编码的文件时,会在文件开始的地方插入三个不可见的字符(0xEF 0xBB 0xBF,即BOM).它是一串隐藏的字符,用于让记事本等编辑器识别这个文 ...