JAVA第十四天(二)
Map
名称 | Map | HashMap | TreeMap | HashTable | LinkedHashMap |
---|---|---|---|---|---|
相同 | 数据成对出现; 数据的键是唯一的; 一个键只能对应一个值; 值可以重复; | ~ | ~ | ~ | ~ |
不同 | 允许多个空值(null value); 一个空键(null key); | 允许多个空值(null value); 一个空键(null key); 其中元素的顺序为无序并且与添加顺序无关; 不是线程安全的(可变); | 键不能重复且不能为空; 值可多个为空; 其中元素的顺序根据键的自然顺序排序; 不是线程安全的; | 不允许任何空值和空键; 其中元素的顺序为无序并且与添加顺序无关; 不是线程安全的 | 允许多个空值(null value); 一个空键(null key); 其中元素的顺序为添加顺序; 不是线程安全的 |
定义:Map是键值对的集合的接口抽象。
我们可以通过Key值来获得相应的值,将键映射到值的对象。
一个映射不能包含重复的键;每个键最多只能映射到一个值;
若存在相同的键,一开始存在的值将被覆盖
键只允许有一个空值;值可以有多个空值;
Map集合与Collection接口无关。
Key1 | Key2 | Key3 |
---|---|---|
Value1 | Value2 | value3 |
特点:
①数据成对出现
②数据的键是唯一的
③一个键只能对应一个值
④值可以重复
⑤键允许有一个为空,值允许多个为空
创建语法:
K:此映射所维护的键的类型
V:映射类型
Map<k,v> 对象名 = new 实现类名<k,v>();
添加方法
返回值类型 方法名 参数列表
V put(K key, V value)
将指定的值与该映射中的指定键相关联(可选操作)。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生1", "王五");
map.put("学生3", "王五");
System.out.println(map);
输出结果: (注意:同值不同键时,数据不会被覆盖!)
{学生2=李四, 学生1=王五, 学生3=王五} (注意:同键不同值时,数据将被覆盖!)
---------------------------------------------------------------------------------
void putAll(Map<? extends K,? extends V> m)
将指定Map的所有映射复制到此映射(可选操作)。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
System.out.println(map);
Map<String , String> map2 = new HashMap<String,String>();
map2.put("老师1", "张老师");
map2.putAll(map);
System.out.println(map2);
输出结果:
{学生2=李四, 学生1=张三, 学生4=赵六, 学生3=王五}
{老师1=张老师, 学生2=李四, 学生1=张三, 学生4=赵六, 学生3=王五}
---------------------------------------------------------------------------------
删除方法
void clear()
从该Map中删除所有的映射(可选操作)。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
map.clear();
System.out.println(map);
输出结果:
{}
---------------------------------------------------------------------------------
V remove(Object key)
如果存在(从可选的操作),从该地图中删除一个键的映射。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
map.remove("学生2");
System.out.println(map);
输出结果:
{学生1=张三, 学生4=赵六, 学生3=王五}
---------------------------------------------------------------------------------
获取方法
V get(Object key)
返回到指定键所映射的值,如果此映射不包含该键的映射关系,则返回null。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
System.out.println(map.get("学生2"));
输出结果:
李四
---------------------------------------------------------------------------------
Set<K> keySet()
返回此Map中包含的键的Set视图。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
Set<String> set = map.keySet();
System.out.println(set);
输出结果:
[学生2, 学生1, 学生4, 学生3]
---------------------------------------------------------------------------------
进阶用法(打印出所有键对应的值):
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
Set<String> set = map.keySet();
for(String key:set) {
String str = map.get(key);
System.out.print(str+" ");
}
输出结果:
李四 张三 赵六 王五
---------------------------------------------------------------------------------
判断方法
boolean containsKey(Object key)
如果此映射包含指定键的映射,则返回 true 。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
System.out.println(map.containsKey("学生2"));
输出结果:
true
---------------------------------------------------------------------------------
boolean containsValue(Object value)
如果此地图将一个或多个键映射到指定的值,则返回 true 。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
System.out.println(map.containsValue("张三"));
输出结果:
true
---------------------------------------------------------------------------------
boolean isEmpty()
如果此Map不包含键值映射,则返回 true 。
例:
Map<String,String> map = new HashMap<String,String>();
map.put("学生1", "张三");
map.put("学生2", "李四");
map.put("学生3", "王五");
map.put("学生4", "赵六");
map.clear();
System.out.println(map.isEmpty());
输出结果:
true
---------------------------------------------------------------------------------
当判断的类型为对象时
注意:在判断对象类型的值是否包含时要重写对象类中的equals方法!
Student类
/**
* Student类
*/
public class Student {
//定义学生类成员变量
private int id;
private String name;
private int age;
/*
* 封装学生类的成员变量
*/
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//生成相应的构造器
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
//重写toString方法
@Override
public String toString() {
return "Student [学号=" + id + ", 姓名=" + name + ", 年龄=" + age + "]";
}
//重写equals方法
@Override
public boolean equals(Object obj) {
//判断是否为Student的对象
if(!(obj instanceof Student)) {
return false;
}
//由于被传过来的对象被转换为成Object类型,所以这里再转换回去
Student student = (Student)obj;
if(this.id == student.id &&
this.name != null && student.name != null &&
student.name.equals(this.name) &&
this.age == student.age) {
return true;
}else {
return false;
}
}
//重写hashCode方法
@Override
public int hashCode() {
return 1;
}
}
测试类
Map<String,Student> map = new HashMap<String,Student>();
map.put("key1", new Student(1, "张三", 20));
map.put("key2", new Student(2, "李四", 27));
map.put("key3", new Student(3, "王五", 25));
map.put("key4", new Student(4, "赵六", 23));
System.out.println(map.containsValue(new Student(1, "张三", 20)));
输出结果:
true
遍历方法
Set<Map.Entry<K,V>> entrySet()
返回此Map中包含的映射的Set视图。
例:
Map<String,Student> map = new HashMap<String,Student>();
map.put("key1", new Student(1, "张三", 20));
map.put("key2", new Student(2, "李四", 27));
map.put("key3", new Student(3, "王五", 25));
map.put("key4", new Student(4, "赵六", 23));
// 集合名 目标Map的集合名
Set<Entry<String, Student>> entry = map.entrySet();
for(Entry<String, Student> sp:entry) {
//获得每一个项中的key和value
String key = sp.getKey();
Student s = sp.getValue();
System.out.println(key+" "+s);
}
输出结果:
key1 Student [学号=1, 姓名=张三, 年龄=20]
key2 Student [学号=2, 姓名=李四, 年龄=27]
key3 Student [学号=3, 姓名=王五, 年龄=25]
key4 Student [学号=4, 姓名=赵六, 年龄=23]
---------------------------------------------------------------------------------
使用keyset()、get()与增强for循环
例:
Map<String,Student> map = new HashMap<String,Student>();
map.put("key1", new Student(1, "张三", 20));
map.put("key2", new Student(2, "李四", 27));
map.put("key3", new Student(3, "王五", 25));
map.put("key4", new Student(4, "赵六", 23));
Set<String> set = map.keySet();
for(String key:set) {
Student s = map.get(key);
System.out.println(s);
}
输出结果:
Student [学号=1, 姓名=张三, 年龄=20]
Student [学号=2, 姓名=李四, 年龄=27]
Student [学号=3, 姓名=王五, 年龄=25]
Student [学号=4, 姓名=赵六, 年龄=23]
---------------------------------------------------------------------------------
Map常用语法
首先创建Student类
/**
* Student类
*/
public class Student<Student> {
//定义学生类成员变量
private int id;
private String name;
private int age;
/*
* 封装学生类的成员变量
*/
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//生成相应的构造器
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
//重写toString方法
@Override
public String toString() {
return "Student [学号=" + id + ", 姓名=" + name + ", 年龄=" + age + "]";
}
}
再创建测试类,并在测试类中写下以下代码
public static void main(String[] args) {
Map<String,Student> map = new HashMap<String,Student>();
map.put("key1", new Student(1, "张三", 20));
map.put("key2", new Student(2, "李四", 27));
map.put("key3", new Student(3, "王五", 25));
map.put("key4", new Student(4, "赵六", 23));
System.out.println(map);
}
运行结果:
{key1=Student [学号=1, 姓名=张三, 年龄=20],
key2=Student [学号=2, 姓名=李四, 年龄=27],
key3=Student [学号=3, 姓名=王五, 年龄=25],
key4=Student [学号=4, 姓名=赵六, 年龄=23]}
下面这种用法不常用,但不代表不能这样用
Map<Student,String> map = new HashMap<Student,String>();
map.put(new Student(1, "张三", 20),"key1");
map.put(new Student(2, "李四", 27),"key2");
map.put(new Student(3, "王五", 25),"key3");
map.put(new Student(4, "赵六", 23),"key4");
System.out.println(map);
运行结果:
{Student [学号=1, 姓名=张三, 年龄=20]=key1,
Student [学号=4, 姓名=赵六, 年龄=23]=key4,
Student [学号=3, 姓名=王五, 年龄=25]=key3,
Student [学号=2, 姓名=李四, 年龄=27]=key2}
HashMap
HashMap为Map的实现类,并是实现了Map中的所有方法。
特点:
①HashMap是Map的实现类。
②允许多个null值和一个null键。
③HashMap中的元素没有顺序(与添加顺序无关)。
④HashMap不是线程安全的。
将HashMap变为线程安全的
目标Map集合名 = Collections.synchronizedMap(目标Map集合名);
Map<String,String> map = new HashMap<String,String>();
map = Collections.synchronizedMap(map);
HashMap方法与Map方法一致
TreeMap
TreeMap也为Map的实现类。
TreeMap可以参考TreeSet,TreeMap为可以支持排序的Map。
该映射根据其键的自然顺序进行排序,或根据创建映射是提供的Comparator进行排序,具体取决于使用的构造方法。
特点:
①根据key排序。
②key不能为null,key不能重复,value可多个为空。
③不是线程安全的。
根据key排序代码解释
Map<String,String> map = new TreeMap<String,String>();
map.put("b", "张三");
map.put("a", "李四");
map.put("c", "王五");
map.put("f", "赵六");
System.out.println(map);
运行结果:
{a=李四, b=张三, c=王五, f=赵六}
当TreeMap中存储对象排序时
Student类
public class Student implements Comparable<Student>{
//定义学生类成员变量
private int id;
private String name;
private int age;
/*
* 封装学生类的成员变量
*/
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//生成相应的构造器
public Student(int id, String name, int age) {
super();
this.id = id;
this.name = name;
this.age = age;
}
//重写toString方法
@Override
public String toString() {
return "Student [学号=" + id + ", 姓名=" + name + ", 年龄=" + age + "]"+" ";
}
/**
* 重写Comparable方法
* 首先比较学号,按照学号升序进行排序
* 若学号相同,比较年龄,年龄小的在前
* 若学号、年龄都相同,比较姓名
*/
@Override
public int compareTo(Student stu) {
//先比较学号
int val = this.id - stu.id;
if(val == 0) {
//若学号相同比较年龄
val = this.age - stu.age;
if(val == 0) {
//判断两个对象的姓名是否为空
if(this.name != null && stu.name != null) {
//若学号、年龄都相同,比较姓名
val = this.name.compareTo(stu.name);
}
}
}
return val;
}
}
测试类
public static void main(String[] args) {
Map<Student,String> map = new TreeMap<Student,String>();
map.put(new Student(1, "张三", 20),"key1");
map.put(new Student(4, "李四", 27),"key2");
map.put(new Student(2, "王五", 25),"key3");
map.put(new Student(3, "赵六", 23),"key4");
System.out.println(map);
}
运行结果:
{Student [学号=1, 姓名=张三, 年龄=20] =key1,
Student [学号=2, 姓名=王五, 年龄=25] =key3,
Student [学号=3, 姓名=赵六, 年龄=23] =key4,
Student [学号=4, 姓名=李四, 年龄=27] =key2}
HashTable
HashTable也为Map的实现类。
特点:
①HashTable为Map的实现类。
②不允许任何的null值(value)和null键(key)。
③HashTable中的元素没有顺序(添加顺序无关)。
④HashTable是线程安全的。
LinkedHashMap
LinkedHashMap为Map的实现类。
特点:
①LinkedHashMap是Ma的实现类。
②允许多个null值和一个null。
③LinkedHashMap有顺序(根据添加顺序)。
④LinkedHashMap不是线程安全的。