1. Map接口
1.Map和Collection并列存在,用于保存具有映射关系的键值对Key-Value(双列元素)。
2.Map中的Key和Value是封装在HashMap&Node对象中的。
3.Map中的Key不允许重复,原因和HashSet一样,当有重复的Key时,就等价于替换。
4.Map中可以有多个重复的Value,但需要不同的Key。
5.Map中Key可以为null,但只能有一个,Value可以有多个为空。
6.常用的Map的Key是String,但可以用任何Object类型作为Key。
1.1 底层实现
K-V是存放在HashMap $ Node引用的Node对象中,为了方便遍历,创建了EntrySet集合,其中的元素类型是Entry,它的对象是指向K-V的。
entrySet中,定义的类型是Map.Entry,但是实际上存放的是HashMap $ Node的地址,指向了HashMap $ Node中的K-V,并不是将K-V复制了一份存放到新空间。
entrySet中将K和V分别用实现了Set接口的
1.2 常用方法
import java.util.HashMap;
import java.util.Map;
public class Demo01 {
public static void main(String[] args) {
Map<Object, Object> map = new HashMap<>();
map.put("No1","吕布");
map.put("No2","张飞");
map.put("No1","赵云");//相对键,相当于替换对应值
System.out.println(map);
//根据Key删除映射关系 remove
map.remove("No2");
//获取键对应的值 get
map.get("No1");
//获取元素的个数 size
System.out.println(map.size());
//判读个数是否为0 isEmpty
System.out.println(map.isEmpty());
//清除 clear
map.clear();
//查找键是否存在 containsKey
System.out.println(map.containsKey("赵云"));
}
}
1.3 Map接口的遍历
- 通过取出Key来获取value的值
- 通过Values直接取出所有Value,再用Collection接口的方法遍历
因为Value是在entrySet中是实现了Collection接口的
-通过entrySet返回K-V,又entrySet是实现了Collection接口的,可以用Collection的方法遍历
import java.util.*;
public class Demo02 {
public static void main(String[] args) {
Map<Object, Object> map = new HashMap<>();
map.put("No1", "吕布");
map.put("No2", "张飞");
map.put("No1", "赵云");//相对键,相当于替换对应值
//Map接口的遍历,先取出所有的key,通过key来获取value值
Set key = map.keySet();
//迭代器遍历
Iterator iterator = key.iterator();
while (iterator.hasNext()) {
Object next = iterator.next();
System.out.println(map.get(next));
}
//增强for循环
for (Object obj:
key) {
System.out.println(map.get(key));
}
//也可以通过 Values直接取出所有的value,再通过Collection接口遍历的方法来遍历
Collection values = map.values();
//通过entrySet返回k-v
Set entrySet = map.entrySet();
//增强for循环
for (Object entry:
entrySet) {
Map.Entry m = (Map.Entry) entry;
System.out.println(m.getKey()+"-"+m.getValue());
}
//迭代器
Iterator iterator1= entrySet.iterator();
while (iterator1.hasNext()) {
Object next = iterator1.next();
System.out.println(next);
Map.Entry M = (Map.Entry) next;
System.out.println(M.getKey()+"+"+M.getValue());
}
}
}
例子
- 使用HashMap添加3个员工对象,要求:
键:员工id
值:员工对象
并遍历显示工资>18000的员工(最少两种方式)
员工类:姓名、工资、员工id
import java.util.*;
public class Test {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put(01,new Employee("刘备",30000,01));
map.put(02,new Employee("关羽",20000,02));
map.put(03,new Employee("张飞",-50000,03));
System.out.println("-------------");
//取出key值遍历
Set keys = map.keySet();
for (Object key:
keys) {
Employee employee = (Employee) map.get(key);
if (employee.getSalary()>18000){
System.out.println(employee.getName());
}
}
System.out.println("-------------");
//取出value值遍历
Collection values = map.values();
for (Object value: values) {
Employee employee = (Employee) value;
if (employee.getSalary()>18000){
System.out.println(employee.getName());
}
}
System.out.println("-------------");
//取出K-V进行遍历
Set entrySet = map.entrySet();
for (Object entry:entrySet) {
Map.Entry et = (Map.Entry) entry;
Employee employee = (Employee) et.getValue();
if (employee.getSalary()>18000){
System.out.println(employee.getName());
}
}
System.out.println("-------------");
//迭代器
Iterator iterator = entrySet.iterator();
while (iterator.hasNext()) {
Object entry = iterator.next();
Map.Entry et = (Map.Entry) entry;
Employee employee = (Employee) et.getValue();
if (employee.getSalary()>18000){
System.out.println(employee.getName());
}
}
}
}
class Employee{
private String name;
private int salary;
private int id;
public Employee(String name, int 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 getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", salary=" + salary +
", id=" + id +
'}';
}
}
2. HashMap 类
1.执行构造器 new HashMap()
初始化加载因子 loadfactor = 0.75
HashMap$Node[] table = null
2.执行put调用hash方法,计算key的hash值(h=key.hashCode())^(h>>>16)
3.执行putVal方法建立Node数组,创建table表,初始容量为16,按key的hash值获得索引,判断索引是否为空,创建Node空间,加入k-v
++size,比较size和临界值(12),如果size大于12,扩容。
3. HashTable 类
1.hashtable存放的也是键值对
2.hashtable的k和v都不能为null
3.hashtable的方法基本上和hashmap一致
4.hashtable是线程安全的
底层
底层有一个hashtable$entry数组,table表指向这个数组,初始化大小为11
临界值threshold=8
扩容:左移一位+1
3.1 Properties类
继承了Hashtable类,实现了Map接口
特点和Hashtable类似
可以用于properties文件中,加载数据到properties类对象,进行读取和修改
properties文件通常作为配置文件