Map
-
概述:将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值
-
Map接口和Collection接口的不同:
(1)Map是双列集合,Collection是单列的
(2)Map的键唯一,Collection的子体系Set是唯一的
(3)Map集合的数据结构只针对键,跟值无关,Collection集合的数据结构针对元素有效 -
功能概述
(1)添加功能
V put(K key,V value):给集合添加元素,也可以说是替换集合元素
如果键是第一次存储,就直接存储元素,返回null
如果键已经存在,就用映射的值替换之前的值,返回被替换的值
package org.org.westos.demo;
import java.util.HashMap;
public class MyClass {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
//调用put方法添加集合元素
//第一次存储返回null
String s = map.put("01", "张三");
System.out.println(s);
//第二次存储相同键的值,替换前一个的值,返回被替换的值
String s1 = map.put("01", "李四");
System.out.println(s1);
map.put("02","王五");
map.put("03","赵六");
System.out.println(map);
}
}
(2)删除功能
void clear():清空集合元素
V remove(Object key):根据键删除键值对元素,并返回该值
package org.org.westos.demo;
import java.util.HashMap;
public class MyClass {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
//调用put方法添加集合元素
map.put(01, "张三");
map.put(02, "李四");
map.put(03,"王五");
map.put(04,"赵六");
//调用remove方法,根据键删除值,返回被删除的值
String remove = map.remove(01);
System.out.println(remove);
System.out.println(map);
//调用clear方法清空集合元素
map.clear();
System.out.println(map);
}
}
(3)判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
int size():获取集合中键值对对数
package org.org.westos.demo;
import java.util.HashMap;
public class MyClass {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
//调用put方法添加集合元素
map.put(01, "张三");
map.put(02, "李四");
map.put(03, "王五");
map.put(04, "赵六");
//调用containsKey方法判断集合中是否有这个键
boolean b = map.containsKey(01);
System.out.println(b);
//调用containsValue方法判断集合中是否有这个值
boolean b1 = map.containsValue("田七");
System.out.println(b1);
//调用isEmpty方法判断集合是否为空,返回true为空
boolean empty = map.isEmpty();
System.out.println(empty);
//调用size方法获取集合键值对对数
int size = map.size();
System.out.println(size);
}
}
很明显,键01是存在的,返回true;而田七这个值在集合中是不存在的,所以返回false,集合不为空,所以返回false;
(4)获取功能
Set keySet():获取集合中所有键的集合
Collection values():获取集合中所有值的集合
V get(Object key):根据键获取值
Set<Map,Entry<K,V>> entrySet():返回一个键值对的Set集合
package org.org.westos.demo;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MyClass {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
//调用put方法添加集合元素
map.put(01, "张三");
map.put(02, "李四");
map.put(03, "王五");
map.put(04, "赵六");
//调用keySet方法获取所有键的集合
Set<Integer> keySet = map.keySet();
System.out.println(keySet);
//调用values方法获取所有值的集合
Collection<String> values = map.values();
System.out.println(values);
//遍历键集合并调用get方法获取值
for (Integer key : keySet) {
//获取键对应的值
String value = map.get(key);
System.out.println(key+"-"+value);
}
System.out.println("---------");
//上述是把键单独看作一个对象返回键的集合,然后找对应值
//还有一种是调用entrySet方法把键和值一起看作一个对象返回一个集合
//泛型就是map集合的类型
Set<Map.Entry<Integer, String>> entries = map.entrySet();
System.out.println(entries);
//遍历键值对集合
for (Map.Entry<Integer, String> entry : entries) {
//通过getKey方法获得键
Integer key = entry.getKey();
//通过getValue方法获得值
String value = entry.getValue();
System.out.println(key+"-"+value);
}
}
}
从上述代码我们也可以知道,遍历map集合的方式:
(1)通过遍历键集合找对应值
(2)遍历键值对集合获得键、值
Map接口的三个子类
HashMap集合
特点:键唯一,无序
package org.org.westos.demo;
import java.util.HashMap;
import java.util.Set;
public class MyClass {
public static void main(String[] args) {
HashMap<Integer, String> map = new HashMap<>();
map.put(10,"aaa");
map.put(20,"aaa");
map.put(30,"aaa");
map.put(40,"aaa");
map.put(50,"aaa");
map.put(60,"aaa");
//通过键找值遍历
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
String value = map.get(key);
System.out.println(key+"-"+value);
}
}
}
可以看出,输出的顺序是不一样的,而唯一性是键唯一,而不是对应的值唯一
LinkedHashMap集合
特点:键唯一,有序
还是拿上面的代码为例,只不过创建的集合对象变为LinkedHashMap
package org.org.westos.demo;
import java.util.LinkedHashMap;
import java.util.Set;
public class MyClass {
public static void main(String[] args) {
LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
map.put(10,"aaa");
map.put(20,"aaa");
map.put(30,"aaa");
map.put(40,"aaa");
map.put(50,"aaa");
map.put(60,"aaa");
//通过键找值遍历
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
String value = map.get(key);
System.out.println(key+"-"+value);
}
}
}
改用LinkedHashMap集合,输出的内容就是有序的
TreeMap集合
特点:键唯一,可排序
排序方式:自然排序,比较器排序(跟TreeSet排序方式一样)
package org.org.westos.demo;
import java.util.Set;
import java.util.TreeMap;
public class MyClass {
public static void main(String[] args) {
TreeMap<Integer, String> map = new TreeMap<>();
//键不按顺序存储
map.put(111,"aaa");
map.put(444,"aaa");
map.put(222,"aaa");
map.put(555,"aaa");
map.put(666,"aaa");
map.put(333,"aaa");
//通过键找值遍历
Set<Integer> keySet = map.keySet();
for (Integer key : keySet) {
String value = map.get(key);
System.out.println(key+"-"+value);
}
}
}
这里采用了自然排序,Integer已经重写了conparableTo方法
如果你要自己写一个类创建对象,而且还要对这个对象里的键进行排序,采用自然排序,就要实现Comparable接口,并重写其中的compareTo方法,采用比较器排序,就要获取一个比较器Comparator(接口)实现该接口中的compareTo方法,一般推荐使用匿名内部类,可直接在主方法操作
这里就不演示了,想了解可以回看Set接口以及三个子类这一章
HashMap跟HashTable的区别
(1)相同点:
底层数据结构都是哈希表
(2)不同点:
HashMap:线程不安全,效率高,允许null值null键
HashTable:线程安全,效率低,不允许null值null键
package org.org.westos.demo;
import java.util.HashMap;
import java.util.Hashtable;
public class MyClass {
public static void main(String[] args) {
//创建HashMap集合
HashMap<String, String> map = new HashMap<>();
//添加null值null键
map.put(null,null);
System.out.println(map);
//创建HashTable集合
Hashtable<String, String> table = new Hashtable<>();
//添加null值null键
//一运行就会报错,其中一个为null也会报错
//table.put(null,"a");
// table.put("a",null);
table.put(null,null);
System.out.println(table);
}
}
补充
之前在说Set接口时提到高HashSet底层是拿HashMap存储的
随便写一个HashSet集合,然后添加元素,在代码上,按住Ctrl点击add方法,进入源代码
再次按住Ctrl点击put方法,进入源代码,而这里的put方法就是HashMap里的添加元素方法
从put源代码看会更加清楚,调用的putVal方法完全就是Map集合的特点,传入的参数有key,有value
那么,putVal方法是怎么实现存储的,可以点进去看源代码,较为繁琐,需要点耐心,这里附一张图便于理解
根据一张图一步步理解吧,多重复看几次相信就能理解的差不多了
集合小结
集合从最开始的Collection到现在的TreeMap就已经全部学完了,作一个小结
当然,每个接口还有很多其他的实现类,但不常用,根据个人如果有需要,自己去学习吧