JAVA深化篇_13——Map接口,HashMap及TreeMap容器详解
Map接口介绍
Map接口定义了双例集合的存储特征,它并不是Collection接口的子接口。双例集合的存储特征是以key与value结构为单位进行存储。体现的是数学中的函数 y=f(x)感念。
Map与Collecton的区别:
- Collection中的容器,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。
- Map中的容器,元素是成对存在的(理解为现代社会的夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
- Collection中的容器称为单列集合,Map中的容器称为双列集合。
- Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
- Map中常用的容器为HashMap,TreeMap等。
Map接口中常用的方法表
方法 | 说明 |
---|---|
V put (K key,V value) | 把key与value添加到Map集合中 |
void putAll(Map m) | 从指定Map中将所有映射关系复制到此Map中 |
V remove (Object key) | 删除key对应的value |
V get(Object key) | 根据指定的key,获取对应的value |
boolean containsKey(Object key) | 判断容器中是否包含指定的key |
boolean containsValue(Object value) | 判断容器中是否包含指定的value |
Set keySet() | 获取Map集合中所有的key,存储到Set集合中 |
Set<Map.Entry<K,V>> entrySet() | 返回一个Set基于Map.Entry类型包含Map中所有映射。 |
void clear() | 删除Map中所有的映射 |
HashMap容器的使用
HashMap采用哈希算法实现,是Map接口最常用的实现类。 由于底层采用了哈希表存储数据,我们要求键不能重复,如果发生重复,新的键值对会替换旧的键值对。 HashMap在查找、删除、修改方面都有非常高的效率。
public class HashMapTest {
public static void main(String[] args) {
//实例化HashMap容器
Map<String,String> map = new HashMap<>();
//添加元素
map.put("a","A");
map.put("b","B");
map.put("c","C");
map.put("a","D");
//获取容器中元素数量
int size = map.size();
System.out.println(size);
System.out.println("---------------");
//获取元素
//方式一
String v = map.get("a");
System.out.println(v);
System.out.println("---------------");
//方式二
Set<String> keys = map.keySet();
for(String key:keys){
String v1 = map.get(key);
System.out.println(key+" ---- "+v1);
}
System.out.println("-------------------");
//方式三
Set<Map.Entry<String,String>> entrySet = map.entrySet();
for(Map.Entry<String,String> entry:entrySet){
String key = entry.getKey();
String v2 = entry.getValue();
System.out.println(key+" ---------- "+v2);
}
System.out.println("--------------------");
//Map容器的并集操作
Map<String,String> map2 = new HashMap<>();
map2.put("f","F");
map2.put("c","CC");
map.putAll(map2);
Set<String> keys2 = map.keySet();
for(String key:keys2){
System.out.println("key: "+key+" Value: "+map.get(key));
}
System.out.println("---------------");
//删除元素
String v3 = map.remove("a");
System.out.println(v3);
Set<String> keys3 = map.keySet();
for(String key:keys3){
System.out.println("key: "+key+" Value: "+map.get(key));
}
System.out.println("-------------------");
//判断Key是否存在
boolean b = map.containsKey("b");
System.out.println(b);
//判断Value是否存在
boolean cc = map.containsValue("CC");
System.out.println(cc);
}
}
HashTable类和HashMap用法几乎一样,底层实现几乎一样,只不过HashTable的方法添加了synchronized关键字确保线程同步检查,效率较低。
HashMap与HashTable的区别
- HashMap: 线程不安全,效率高。允许key或value为null
- HashTable: 线程安全,效率低。不允许key或value为null
TreeMap容器的使用
TreeMap和HashMap同样实现了Map接口,所以,对于API的用法来说是没有区别的。HashMap效率高于TreeMap;TreeMap是可以对键进行排序的一种容器,在需要对键排序时可选用TreeMap。TreeMap底层是基于红黑树实现的。
在使用TreeMap时需要给定排序规则:
- 元素自身实现比较规则
- 通过比较器实现比较规则
元素自身实现比较规则
public class Users implements Comparable<Users>{
private String username;
private int userage;
public Users(String username, int userage) {
this.username = username;
this.userage = userage;
}
public Users() {
}
@Override
public boolean equals(Object o) {
System.out.println("equals...");
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Users users = (Users) o;
if (userage != users.userage) return false;
return username != null ? username.equals(users.username) : users.username == null;
}
@Override
public int hashCode() {
int result = username != null ? username.hashCode() : 0;
result = 31 * result + userage;
return result;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getUserage() {
return userage;
}
public void setUserage(int userage) {
this.userage = userage;
}
@Override
public String toString() {
return "Users{" +
"username='" + username + '\'' +
", userage=" + userage +
'}';
}
//定义比较规则
//正数:大,负数:小,0:相等
@Override
public int compareTo(Users o) {
if(this.userage < o.getUserage()){
return 1;
}
if(this.userage == o.getUserage()){
return this.username.compareTo(o.getUsername());
}
return -1;
}
}
public class TreeMapTest {
public static void main(String[] args) {
//实例化TreeMap
Map<Users,String> map = new TreeMap<>();
Users u1 = new Users("oldlu",18);
Users u2 = new Users("admin",22);
Users u3 = new Users("sxt",22);
map.put(u1,"oldlu");
map.put(u2,"admin");
map.put(u3,"sxt");
Set<Users> keys = map.keySet();
for(Users key :keys){
System.out.println(key+" --------- "+map.get(key));
}
}
}
通过比较器实现比较规则
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
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;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}
public class StudentComparator implements Comparator<Student> {
//定义比较规则
@Override
public int compare(Student o1, Student o2) {
if(o1.getAge() > o2.getAge()){
return 1;
}
if(o1.getAge() == o2.getAge()){
return o1.getName().compareTo(o2.getName());
}
return -1;
}
}
public class TreeMapTest {
public static void main(String[] args) {
Map<Student,String> treeMap = new TreeMap<>(new StudentComparator());
Student s1 = new Student("oldlu",18);
Student s2 = new Student("admin",22);
Student s3 = new Student("sxt",22);
treeMap.put(s1,"oldlu");
treeMap.put(s2,"admin");
treeMap.put(s3,"sxt");
Set<Student> keys1 = treeMap.keySet();
for(Student key :keys1){
System.out.println(key+" ---- "+treeMap.get(key));
}
}
}