目录
Map接口特点
Map接口实现类的特点
注意:这里是JDK8的Map接口特点
-
Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
-
Map中的key和value 可以是任何引用类型的数据,会封装到HashMap$Node对象中
-
Map中的 key不允许重复,原因和HashSet一样,前面分析过源码.
-
Map中的 value 可以重复
-
Map的key可以为null,value也可以为null,注意 key为null,只能有一个,value为null,可以多个.
-
常用String类作为Map的 key
-
key和 value之间存在单向一对一关系,即通过指定的 key总能找到对应的value
代码演示:
注意在map接口中,是按照k-v的形式来存放数据的,即就是键值对,我们可以根据key找到对应的value
package idea.chapter14.map_;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings({"all"})
public class Map_ {
public static void main(String[] args) {
//Map 接口实现类的特点, 使用实现类HashMap
//1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(双列元素)
//2. Map 中的 key 和 value 可以是任何引用类型的数据,会封装到HashMap$Node 对象中
//3. Map 中的 key 不允许重复,原因和HashSet 一样,前面分析过源码.
//4. Map 中的 value 可以重复
//5. Map 的key 可以为 null, value 也可以为null ,注意 key 为null,只能有一个,value 为null ,可以多个
//6. 常用String类作为Map的 key
//7. key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到对应的 value
Map map = new HashMap();
map.put("1", "jack");//k-v
map.put("2", "tom");//k-v
map.put("1", "mary");//当有相同的k , 就等价于替换.
map.put("3", "smith");//k-v
map.put(null, null); //k-v
map.put(null, "abc"); //等价替换
map.put("4", null); //k-v
map.put("5", null); //k-v
map.put(new Object(), "你好");//k-v
// 通过get 方法,传入 key ,会返回对应的value
System.out.println(map.get("2"));//tom
System.out.println("map=" + map);
}
}
8.Map存放数据的key-value示意图,一对 k-v是放在一个HashMap$Node中的,有因为Node实现了 Entry接口
代码演示:
package idea.chapter14.map_;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@SuppressWarnings({"all"})
public class MapSource_ {
public static void main(String[] args) {
Map map = new HashMap();
map.put("1", "jack");//k-v
map.put("2", "tom");//k-v
map.put(new Car(), new Person());//k-v
//1. k-v 最后是 HashMap$Node node = newNode(hash, key, value, null)
//2. k-v 为了方便程序员的遍历,还会 创建 EntrySet 集合 ,该集合存放的元素的类型 Entry, 而一个Entry
// 对象就有k,v EntrySet<Entry<K,V>> 即: transient Set<Map.Entry<K,V>> entrySet;
//3. entrySet 中, 定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node
// 这时因为 static class Node<K,V> implements Map.Entry<K,V>
//4. 当把 HashMap$Node 对象 存放到 entrySet 就方便我们的遍历, 因为 Map.Entry 提供了重要方法
// K getKey(); V getValue();
Set set = map.entrySet();
System.out.println(set.getClass());// HashMap$EntrySet
for (Object obj : set) {
//System.out.println(obj.getClass()); //HashMap$Node
//为了从 HashMap$Node 取出k-v
//1. 先做一个向下转型
Map.Entry entry = (Map.Entry) obj;
System.out.println(entry.getKey() + "-" + entry.getValue() );
}
Set set1 = map.keySet();
System.out.println(set1.getClass());
Collection values = map.values();
System.out.println(values.getClass());
}
}
class Car {
}
class Person{
}
Map接口和常用方法
1.put:添加
2.remove:根据键删除映射关系
3.get:根据键获取值
4.size:获取元素个数
5.isEmpty:判断个数是否为0
6.clear:清除
7.containsKey:查找键是否存在
代码演示:
package idea.chapter14.map_;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings({"all"})
public class MapMethod {
public static void main(String[] args) {
//演示map接口常用方法
Map map = new HashMap();
map.put("邓超", new Book("", 100));//OK
map.put("邓超", "孙俪");//替换-> 一会分析源码
map.put("王宝强", "马蓉");//OK
map.put("宋喆", "马蓉");//OK
map.put("刘令博", null);//OK
map.put(null, "刘亦菲");//OK
map.put("鹿晗", "关晓彤");//OK
System.out.println("map=" + map);
// remove:根据键删除映射关系
map.remove(null);
System.out.println("map=" + map);
// get:根据键获取值
Object val = map.get("鹿晗");
System.out.println("val=" + val);
// size:获取元素个数
System.out.println("k-v=" + map.size());
// isEmpty:判断个数是否为0
System.out.println(map.isEmpty());//F
// clear:清除k-v
//map.clear();
System.out.println("map=" + map);
// containsKey:查找键是否存在
System.out.println("结果=" + map.containsKey("hsp"));//T
}
}
class Book {
private String name;
private int num;
public Book(String name, int num) {
this.name = name;
this.num = num;
}
}
Map接口遍历方法
-
containsKey:查找键是否存在
-
keySet:获取所有的键
-
entrySet:获取所有关系k-v
-
values:获取所有的值
代码演示:
package idea.chapter14.map_;
import java.util.*;
@SuppressWarnings({"all"})
public class MapFor {
public static void main(String[] args) {
Map map = new HashMap();
map.put("1", "jack");//k-v
map.put("2", "tom");//k-v
map.put("1", "mary");//当有相同的k , 就等价于替换.
map.put("3", "smith");//k-v
map.put(null, null); //k-v
//第一组: 先取出 所有的Key , 通过Key 取出对应的Value
Set keyset = map.keySet();
//(1) 增强for
System.out.println("-----第一种方式-------");
for (Object key : keyset) {
System.out.println(key + "-" + map.get(key));
}
//(2) 迭代器
System.out.println("----第二种方式--------");
Iterator iterator = keyset.iterator();
while (iterator.hasNext()) {
Object key = iterator.next();
System.out.println(key + "-" + map.get(key));
}
//第二组: 把所有的values取出
Collection values = map.values();
//这里可以使用所有的Collections使用的遍历方法
//(1) 增强for
System.out.println("---取出所有的value 增强for----");
for (Object value : values) {
System.out.println(value);
}
//(2) 迭代器
System.out.println("---取出所有的value 迭代器----");
Iterator iterator2 = values.iterator();
while (iterator2.hasNext()) {
Object value = iterator2.next();
System.out.println(value);
}
//第三组: 通过EntrySet 来获取 k-v
Set entrySet = map.entrySet();// EntrySet<Map.Entry<K,V>>
//(1) 增强for
System.out.println("----使用EntrySet 的 for增强(第3种)----");
for (Object entry : entrySet) {
//将entry 转成 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
//(2) 迭代器
System.out.println("----使用EntrySet 的 迭代器(第4种)----");
Iterator iterator3 = entrySet.iterator();
while (iterator3.hasNext()) {
Object entry = iterator3.next();
//System.out.println(next.getClass());//HashMap$Node -实现-> Map.Entry (getKey,getValue)
//向下转型 Map.Entry
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey() + "-" + m.getValue());
}
}
}
Map接口练习
代码演示:
注意事项:
1.在使用增强for遍历时
//注意转成emp类型时,转的时value,并不是key 如果转的是key,会报类型转换异常 所以我们这里通过hashMap的get方法得到key对应的值,然后进行向下转型
2.使用迭代器遍历时 // 在转成emp类型时,转的时value,并不是key 如果转的是key,会报类型转换异常 所以我们这里 //先将其转成Map.Entry类型 然后使用Entry中提供的getValue()方法,直接获取到值,不在需要key来得到对应的值
package idea.chapter14.map_;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/*
使用HashMap添加3个员工对象,要求
键:员工id
值:员工对象
并遍历显示工资>18000的员工(遍历方式最少两种)员工类:姓名、工资、员工id
*/
@SuppressWarnings({"all"})
public class MapExercise {
public static void main(String[] args) {
Map hashMap = new HashMap();
//添加数据
hashMap.put(1, new Emp("jack", 300000, 1));
hashMap.put(2, new Emp("tom", 21000, 2));
hashMap.put(3, new Emp("milan", 12000, 3));
//遍历2种方式
//并遍历显示工资>18000的员工
//1. 使用keySet -> 增强for
Set keySet = hashMap.keySet();
System.out.println("====第一种遍历方式====");
for (Object key : keySet) {
//先获取value
//注意转成emp类型时,转的时value,并不是key 如果转的是key,会报类型转换异常 所以我们这里通过hashMap的get方法得到key对应的值,然后进行向下转型
Emp emp = (Emp) hashMap.get(key);
if (emp.getSalary() > 18000) {
System.out.println(emp);
}
}
//2. 使用EntrySet -> 迭代器
Set entrySet = hashMap.entrySet();
System.out.println("======迭代器======");
Iterator iterator = entrySet.iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
//这里也同理
// 在转成emp类型时,转的时value,并不是key 如果转的是key,会报类型转换异常 所以我们这里
//先将其转成Map.Entry类型 然后使用Entry中提供的getValue()方法,直接获取到值,不在需要key来得到对应的值
//通过entry 取得key 和 value
Emp emp = (Emp) entry.getValue();
if (emp.getSalary() > 18000) {
System.out.println(emp);
}
}
}
}
class Emp {
private String name;
private double salary;
private int id;
public Emp(String name, double salary, int id) {
this.name = name;
this.salary = salary;
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", id=" + id +
", salary=" + salary +
'}';
}
}
HashMap小结
1.Map接口的常用实现类:HashMap、Hashtable和Properties。
2.HashMap是Map接口使用频率最高的实现类。
3.HashMap是以 key-val对的方式来存储数据(HashMap$Node类型)[案例Entry]
4)key 不能重复,但是值可以重复,允许使用null键和null值。
5)如果添加相同的key,则会覆盖原来的key-val,等同于修改.(key不会替换,val会替换)
6)与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的.(jdk8的hashMap底层 数组+链表+红黑树)
7)HashMap没有实现同步,因此是线程不安全的,方法没有做同步互斥的操作,没有synchronized