Map集合
5.0 重点掌握
- 能够说出Map集合的特点
- 能够使Map集合添加方法保存数据
- 使用“键找值””键值对“的方式遍历Map集合
- 使用HashMap存储自定义键值对的数据
- 完成HashMap案例
5.1 Map集合概述
现实生活中,经常会出现这么一种集合:如 身份证与个人,ip与主机名等,这种一一对应的关系,就叫做映射,
Java提供了专门的集合来存放这种对象关系映射,即java.util.Map接口
其中,Map接口和Collection接口存储数据的形式是不同的
- Collection接口定义了单列集合规范,每次存储一个元素。Collection
- Collection中的集合,元素是独立存在的 ( 单身狗 ),向集合中存储元素采用一个一个的方式存储
- Map接口定义了双列集合的规范,每次存放一对元素。Map<K,V>
- Map中的集合。元素是成对成对的 ( 小情侣 ),每个元素由键和值两部分组成,通常键可以找到指定的值,
- Map中的集合,键是唯一的,值可以重复,每个键只能对应一个值
5.2 Map常用的子类
Map有多个子类,其中常用的事HashMap和LinkedHashMap
- HashMap<K,V> : 存储数据采用的是哈希表结构,元素的存取顺序不能保持一致,由于要保证键的唯一,不重复,需要重写键的hashCode()方法、equals()方法
- LinkedHashMap(K,V) :HashMap下的子类LinkedHashMap,存储数据采用的事哈希表+链表结构,通过链表结构可以保证元素的存储顺序一致。通过哈希表结构可以保证键的唯一和不重复。需要重写键的hashCode()方法和equals()方法
5.3 Map接口中的常用方法
Map接口中定义了很多方法:常用如下:
Map接口常用方法案例
import java.util.HashMap;
import java.util.Map;
public class Demo01Map {
/*
Map集合的特点
1、Map是一个双列集合,一个元素包含两个值:一个key一个value
2、Map集合中的元素,key和value的数据类型,可以相同,也可以不同
3、Map集合中的元素,key是不允许重复的,value是可以重复的
4、Map集合中的元素,key和value是一一对应的
HashMap实现了Map接口
1、HashMap底层是哈希表,查询速度快
2、HashMap是一个无序的集合,存储元素和取出元素的顺序可能不一致
LinkHashMap继承自HashMap
1、LinkHashMap集合底层是哈希表+链表,保证了迭代的顺序
2、LinkHashMap是一个有序的集合,存储元素和取出元素的顺序是一致的
*/
public static void main(String[] args) {
/*
1 将指定的值与此映射中的指定键相关联
public V put(K key, V value)
返回值:V
key不重复,返回值是null
key重复,原先value被覆盖,返回覆盖的value值
*/
method1();
/*
2 从该集合中删除指定键的映射(如果存在
public V remove(Object key)
返回值:V
key存在,键值对被删除,返回被删除的key对应的值
key不存在,返回值为null
*/
method2();
/*
3 如果此映射包含指定键的映射,则返回 true
boolean containsKey(Object key)
包含返回true,不包含返回false
*/
method3();
/*
4 public V get(Object key)
返回到指定键所映射的值
返回值:V
如果key存在,返回对应的value的值
如果key不存在,返回null
*/
method4();
}
private static void method4() {
Map<Integer,String> map = new HashMap<>();
map.put(1,"赵四");
map.put(2,"刘能");
map.put(3,"谢广坤");
map.put(4,"王老七");
String s1 = map.get(1);
System.out.println(s1);//赵四
String s2 = map.get(5);//null
System.out.println(s2);
System.out.println(map);
}
private static void method3() {
Map<String,String> map = new HashMap<>();
map.put("悟空","猴子");
map.put("八戒","飞猪");
map.put("白龙马","小白龙");
boolean b1 = map.containsKey("八戒");
System.out.println(b1);//true
boolean b2 = map.containsKey("唐僧");
System.out.println(b2);//false
System.out.println(map);
}
private static void method2() {
Map<String,String> map = new HashMap<>();
map.put("季军","克罗地亚");
map.put("亚军","法国");
map.put("冠军","阿根廷");
String s1 = map.remove("亚军");
System.out.println(s1);//法国
String s2 = map.remove("冷军");
System.out.println(s2);//null
System.out.println(map);
}
private static void method1() {
Map<String, String> map = new HashMap<>();
String s1 = map.put("阿根廷", "梅西");
System.out.println(s1);//null
String s2 = map.put("阿根廷", "夺冠");
System.out.println(s2);//梅西
System.out.println(map);
}
}
5.4 Map集合遍历键找值方式
步骤图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sYp0FDSH-1681714245814)(photo/JavaSE12_集合.assest/1671431571924.png)]
Map集合遍历键找值方式案例
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Demo02_MapKeySet {
/*
Map集合的遍历
方式一:通过键找值的方式
返回Map中包含的键的Set视图。
Set<K> keySet();
实现步骤:
1、使用Map集合中的keySet()方法,将Map集合中所有的key取出,存储在Set集合中
2、遍历Set集合,获取Map集合中的每个Key
3、通过Map集合中的get(key)方法,通过key找到value
*/
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1,"tom");
map.put(2,"anny");
map.put(3,"jack");
map.put(4,"mary");
//1、第一步使用keySet()方法。将key存储在Set集合中
Set<Integer> s1 = map.keySet();
//2、第二步,遍历Set集合
//迭代器遍历
Iterator<Integer> iterator = s1.iterator();
while (iterator.hasNext()){
Integer key = iterator.next();
//3、第三步,获取Map集合中key对应的value
String value = map.get(key);
System.out.println(key+"="+value);
}
System.out.println("--------------------");
//加强for遍历
for (Integer key : s1) {
//3、第三步,获取Map集合中key对应的value
String value = map.get(key);
System.out.println(key+"="+value);
}
}
}
5.5 Entry键值对对象
Map中存放的是两种对象,一种称为key键,一种称为value值,它们是一一对应的关系
这样的一对对象又称之为Map的一个Entry项,Entry将键值对的对应关系封装成了对象,即键值对对象
在遍历Map集合的时候,就可以从每一个键值对对象Entry中获取对应的键和对应的值
Entry表示一对键和值,同时提供了获取对应键和对应值的方法
- public V getKey( ); 获取Entry对象中的键
- publi V getValue( ); 获取Entry对象中的值
Map集合提供了获取所有Entry对象的方法
- public Set<Map.Entry<K,V>> entrySet( ); 获取所有Map集合中的键值对对象的集合(Set集合)
5.6 Map集合遍历键值对方式
遍历步骤:
遍历键值对方式:通过集合中每个键值对对象Entry,获取键值对对象Entry中的键和值
实现步骤:
- 1、获取Map集合中的所有键值对Entry对象,以Set集合的形式返回,使用entrySet()
- 2、遍历Set集合,得到每一个Entry对象
- 3、通过键值对Entry对象,获取Entry对象的键和值,方式使用getKey()和getValue()
Map集合遍历键值对方式案例
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Demo03_MapEntrySet {
/*
遍历键值对方式:
通过集合中每个键值对对象Entry,
获取键值对对象Entry中的键和值
实现步骤:
1、获取Map集合中的所有键值对Entry对象,以Set集合的形式返回,使用entrySet()
2、遍历Set集合,得到每一个Entry对象
3、通过键值对Entry对象,获取Entry对象的键和值,方式使用getKey()和getValue()
*/
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
map.put(1,"卡卡");
map.put(2,"姆巴佩");
map.put(3,"梅西");
map.put(4,"C罗");
//1、获取Map集合中的所有键值对Entry对象,以Set集合的形式返回,使用entrySet()
Set<Map.Entry<Integer, String>> set = map.entrySet();
//2、遍历Set集合,得到每一个Entry对象
//迭代器遍历set集合
Iterator<Map.Entry<Integer, String>> it = set.iterator();
while (it.hasNext()){
Map.Entry<Integer, String> entry = it.next();
//3、通过键值对Entry对象,获取Entry对象的键和值,方式使用getKey()和getValue()
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"="+value);
}
System.out.println("-------------------------");
//加强for遍历set集合
for (Map.Entry<Integer, String> entry:set){
//3、通过键值对Entry对象,获取Entry对象的键和值,方式使用getKey()和getValue()
Integer key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
5.7 HashMap存储自定义类型键值
HashMap存储自定义类型键值,Map集合保证key是唯一的,
作为key的元素,必须重写hashCode()和equals()方法。
案例:
import java.util.Objects;
public class User {
private String name;
private String address;
public User() {
}
public User(String name, String address) {
this.name = name;
this.address = address;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(name, user.name) && Objects.equals(address, user.address);
}
@Override
public int hashCode() {
return Objects.hash(name, address);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Demo04_MapDefined {
public static void main(String[] args) {
/*
方式1:String字符串作为key,user对象作为value
key相同,值会覆盖
*/
method1();
System.out.println("------------------");
/*
方式2:user对象作为key。字符串作为value
使用对象作为key,必须重写实体类的hashCode和equals方法
否则,key相同,值也不会覆盖
*/
method2();
}
private static void method1() {
Map<String,User> map = new HashMap<>();
map.put("东北",new User("赵本山","辽宁"));
map.put("华北",new User("司马南","北京"));
map.put("华南",new User("刘德华","香港"));
map.put("东北",new User("小沈阳","哈尔冰"));
//1、通过keySet获取Map集合所有的key
Set<String> set = map.keySet();
//2.加强for遍历Set集合,得到key,再通过key获取Map集合中的value
for (String key:set) {
//3、通过key获取value
User user = map.get(key);
System.out.println(key+"="+user);
}
}
private static void method2() {
Map<User,String> map = new HashMap<>();
map.put(new User("张三","北京"),"喜欢篮球");
map.put(new User("李四","上海"),"喜欢排球");
map.put(new User("王五","广州"),"喜欢足球");
map.put(new User("张三","北京"),"喜欢棒球");
//1、使用wntrySet()获取Map集合中的键值对对象Entry
Set<Map.Entry<User, String>> entrySet = map.entrySet();
//2.使用迭代器遍历获取entry对象
Iterator<Map.Entry<User, String>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<User, String> entry = it.next();
//3、获取entry中的键和值
User user = entry.getKey();
String value = entry.getValue();
System.out.println(user+"="+value);
}
}
}
- 重写之后,key相同,值会被覆盖
- 未重写,key相同,值不会被覆盖
5.8 LinkedHashMap
HashMap保证课成对元素的唯一,但是无法保证数据的有序。其子类LinkedHashMap即可以实现
LinkedHashMap的底层是链表+哈希表的存储结构,链表用于记录元素的顺序
- HashMap 存取顺序不同
- LinkedHashMap 存取顺序相同
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class Demo05_LinkedHashMap {
public static void main(String[] args) {
//1、创建HashMap对象,添加数据并打印
HashMap<String,String> map = new HashMap<>();
map.put("a","英文");
map.put("c","俄文");
map.put("b","中文");
map.put("d","德文");
System.out.println(map);
//2、创建LinkedHashMap对象,添加数据并打印
LinkedHashMap<Integer,String> linkedHashMap = new LinkedHashMap();
linkedHashMap.put(1,"AAA");
linkedHashMap.put(3,"CCC");
linkedHashMap.put(2,"BBB");
linkedHashMap.put(4,"DDD");
System.out.println(linkedHashMap);
}
}
5.9 HashMap和HashTable的区别
- HashTable实现了Map接口
- HashTable底层是哈希表,是一个线程安全的集合,是单线程集合,速度慢
- HashMap底层也是哈希表,是一个线程不安全的集合,是多线程集合,速度快
- HashMap可以存储null值,null键。但是HashTable不可以存储null值,null键
- HashTable在1,2版本之后被HashMap、Arraylist取代了,但是其子类Properties集合依然在使用
- Properties集合是一个唯一可以与IO流两结合的集合
import java.util.HashMap;
import java.util.Hashtable;
public class Demo06_HashTable {
public static void main(String[] args) {
//!、创建HashMap集合,存储null值,null键,并打印输出
HashMap<String, String> map = new HashMap<>();
map.put(null, "AAA");
map.put("A", null);
map.put(null, null);
System.out.println(map);
//2、创建HashTable集合,存储null值,null键,并打印输出
Hashtable<Integer, String> table = new Hashtable<>();
table.put(1, "AAA");
table.put(null, "BBB");
table.put(2, null);
table.put(null, null);
System.out.println(table);
/*
Hashtable的键和值都不能为null,否则会报空指针异常
*/
}
}