目录
Map接口实现类特点
- 用于保存具有映射关系的数据Key-Value
- Map中的key和value可以是任意引用类型的数据,会封装到HashMap$Node对象中
- Map中的key不允许重复,原因和HashSet一样
- Map中的value可以重复
- Map中的key可以为null,value也可以为null,key为null只能有一个,value为null可以有多个,和第4点前后呼应
- 常用String类作为Map的key
- Key和value之间存在单向一对一的关系,即通过key可以找到对应的value值
- Map存放的数据是Key-Value
Map接口和常用方法
Map体系的继承图
Map接口的常用方法
public class MapMethod {
public static void main(String[] args) {
Map map = new HashMap();
//1. put
map.put("小丸子", "樱桃小丸子");
map.put("桔梗", "犬夜叉");
map.put("月野兔", "美少女战士");
map.put("唐三", "同样的key,value会覆盖");
map.put("唐三", "斗罗大陆");
map.put(null, "null key");
map.put("null value", null);
map.put("学校", new School("哈哈大学"));
System.out.println(map);// {null=null key, 学校=com.example.hanshunping.map.School@4d7e1886, 唐三=斗罗大陆, 小丸子=樱桃小丸子, null value=null, 月野兔=美少女战士, 桔梗=犬夜叉}
//2.get
System.out.println(map.get("月野兔"));// 美少女战士
//3.size
System.out.println(map.size());// 7
//4.isEmpty
System.out.println(map.isEmpty());// false
//5.containsKey
System.out.println(map.containsKey("猪太郎"));// false
System.out.println(map.containsKey("小丸子"));// true
//6.remove
System.out.println(map.remove("test"));// null
Object remover = map.remove(null);
System.out.println(remover.getClass());// class java.lang.String
System.out.println(map);// {学校=com.example.hanshunping.map.School@4d7e1886, 唐三=斗罗大陆, 小丸子=樱桃小丸子, null value=null, 月野兔=美少女战士, 桔梗=犬夜叉}
//7.clear
map.clear();
System.out.println(map);// {}
}
}
class School {
private String name;
public School(String name) {
this.name = name;
}
}
Map接口的元素遍历方式
public class MapFor {
public static void main(String[] args) {
Map map = new HashMap();
map.put("小丸子", "樱桃小丸子");
map.put("桔梗", "犬夜叉");
map.put("月野兔", "美少女战士");
map.put("唐三", "斗罗大陆");
//1.keySet
//(1)增强for
System.out.println("=====1.keySet 增强for=====");
for (Object key : map.keySet()) {
System.out.println(key + "-" + map.get(key));
}
//(2)迭代器
System.out.println("=====1.keySet 迭代器=====");
Iterator iterator = map.keySet().iterator();
while (iterator.hasNext()) {
Object next = iterator.next();// 这里iterator.next()的类型是class java.lang.String
System.out.println(next);
}
//2.values
//(1)增强for
System.out.println("=====2.values 增强for=====");
for (Object value : map.values()) {
System.out.println(value);
}
//(2)迭代器
System.out.println("=====2.values 迭代器=====");
Collection values = map.values();
Iterator valuesIterator = values.iterator();
while (valuesIterator.hasNext()) {
Object next = valuesIterator.next();// valuesIterator.next()的类型是class java.lang.String
System.out.println(next);
}
//3.entrySet
Set set = map.entrySet();
//(1)增强for
System.out.println("=====3.entrySet 增强for=====");
for (Object o : set) {
Map.Entry entry = (Map.Entry) o;// o的类型是class java.util.HashMap$Node
System.out.println(entry.getValue() + "-" + entry.getValue());
}
//(2)迭代器
System.out.println("=====3.entrySet 迭代器=====");
Iterator entrySetIterator = set.iterator();
while (entrySetIterator.hasNext()) {
Object next = entrySetIterator.next();// entrySetIterator.next()的类型是class java.util.HashMap$Node
Map.Entry entry = (Map.Entry) next;
System.out.println(entry.getValue() + "-" + entry.getValue());
}
}
}
=====1.keySet 增强for=====
唐三-斗罗大陆
小丸子-樱桃小丸子
月野兔-美少女战士
桔梗-犬夜叉
=====1.keySet 迭代器=====
唐三
小丸子
月野兔
桔梗
=====2.values 增强for=====
斗罗大陆
樱桃小丸子
美少女战士
犬夜叉
=====2.values 迭代器=====
斗罗大陆
樱桃小丸子
美少女战士
犬夜叉
=====3.entrySet 增强for=====
斗罗大陆-斗罗大陆
樱桃小丸子-樱桃小丸子
美少女战士-美少女战士
犬夜叉-犬夜叉
=====3.entrySet 迭代器=====
斗罗大陆-斗罗大陆
樱桃小丸子-樱桃小丸子
美少女战士-美少女战士
犬夜叉-犬夜叉
Map接口课堂练习
public class MapExercise {
public static void main(String[] args) {
Map map = new HashMap();
Employee jack = new Employee("jack", 1001, 31000);
Employee rose = new Employee("rose", 1002, 25000);
Employee jacky = new Employee("jacky", 1003, 9000);
map.put(jack.getId(), jack);
map.put(rose.getId(), rose);
map.put(jacky.getId(), jacky);
// keySet-增强for遍历
System.out.println("=====keySet-增强for遍历=====");
Employee employee = null;
for (Object key : map.keySet()) {
employee = (Employee) map.get(key);
if (employee.getSalary() > 18000) {
System.out.println(employee.toString());
}
}
// entrySet-迭代器遍历
System.out.println("=====entrySet-迭代器遍历=====");
Set set = map.entrySet();
Iterator iterator = set.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
Map.Entry entry = (Map.Entry) next;
Employee employee1 = (Employee) entry.getValue();
if (employee1.getSalary() > 18000) {
System.out.println(employee1);
}
}
}
}
=====keySet-增强for遍历=====
Employee{name='jack', id=1001, salary=31000.0}
Employee{name='rose', id=1002, salary=25000.0}
=====entrySet-迭代器遍历=====
Employee{name='jack', id=1001, salary=31000.0}
Employee{name='rose', id=1002, salary=25000.0}
Map接口底层代码分析
public class MapSource_ {
public static void main(String[] args) {
Map hashMap = new HashMap();
hashMap.put("no1", "小可爱1号");
hashMap.put("no2", "小可爱2号");
//1. k-v 最后是 HashMap$Node node = newNode(hash, key, value, null);
//2. k-v 为了方便程序员遍历, 还会创建一个EntrySet集合, 该集合存放的元素的类型是Entry, 而一个Entry对象里面就有k,v,EntrySet<Entry<K, V>>
// 底层代码: public Set<Map.Entry<K,V>> entrySet()
Set set = hashMap.entrySet();
System.out.println(set.getClass()); // class java.util.HashMap$EntrySet
//3. entrySet里面数据定义的类型是Map.Entry, 底层代码: Set<Map.Entry<K, V>> entrySet(); 但是实际上存放的还是HashMap$Node.
// 为什么可以把一个Node类型存放到Map.Entry里面呢? 这是因为HashMap$Node实现了Map$Entry. 底层代码:static class Node<K,V> implements Map.Entry<K,V>
for (Object obj : set) {
System.out.println(obj.getClass());// class java.util.HashMap$Node
}
//4. 既然key,value已经存放到HashMap$Node, 那为什么设计者设计的时候, 又把对象存放到了EntrySet里面呢? 这是因为对象存放到entrySet之后, 就方便我们程序员遍历了.
// 为什么会方便程序员遍历呢? 这是因为Map.Entry提供了两个重要的方法 (1)K getKey(); (2)V getValue();
for (Object o : set) {
Map.Entry entry = (Map.Entry) o;
System.out.println(entry.getKey() + "-" + entry.getValue());
}
}
}
class java.util.HashMap$EntrySet
class java.util.HashMap$Node
class java.util.HashMap$Node
no2-小可爱2号
no1-小可爱1号
entry里面的key和value其实是指向node节点 key和value的引用