今天的博客主题
基础篇 --》常用类 --》Java集合类(三)Map
Map
public interface Map<K,V> {}
Map直接就是一个接口,已经约定KV结构的存储。
Map也是一个集合和Collection是一个级别的。
Map集合是双列的,键值对的方式存在的。
Map的体系结构大概是这样子的。
特点
- Map属于是一个映射,是无序的。
- 以键值对的形式添加元素。
- 键不能重复,值可以重复。
- HashMap只允许一条记录的键为NULL。
- 每个键只能映射一个值。
- 插入顺序和访问顺序无法保证
Map只是一个接口,具体实现还得看实现类是怎么来实现的。
HashMap
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {}
HashMap继承AbstractMap类,实现了Map、Cloneable、Serializable接口
AbstractMap实现了Map里的一系列方法。
特点:
- 既然是Map实现类,继承AbstractMap,那Map的特点HashMap是都有的。
- 线程不安全
HashMap是基于哈希表的Map接口实现的,而哈希表的作用就是来保证键是唯一的。
如果要指定HashMap的Key(也就是键)一定要确保重写了equals()和hashCode()两个方法。
核心方法(常用API)
public static void main(String[] args) {
// 创建一个HashMap集合。可以指定集合存放的键值类型
HashMap hashMap = new HashMap();
HashMap<String, Object> hashMapO = new HashMap();
HashMap<String, String> hashMapS = new HashMap();
// 往集合添加元素。键不可重复,重复会覆盖,值可重复
hashMap.put("1","a");
hashMap.put("1","b");
hashMap.put("2","c");
hashMap.put("3","d");
hashMap.put("4","d");
System.out.println(hashMap); // {1=b, 2=c, 3=d, 4=d}
HashMap hashMap2 = new HashMap();
hashMap2.put("5","a");
// 往集合添加一个集合,相同键的值会被覆盖
hashMap.putAll(hashMap2);
System.out.println(hashMap); // {1=b, 2=c, 3=d, 4=d, 5=a}
// 获取集合长度
int size = hashMap.size();
System.out.println(size); // 5
// 验证集合是否为空
boolean empty = hashMap.isEmpty();
System.out.println(empty); // false
// 通过指定键K获取对应值V
Object o = hashMap.get("2");
System.out.println(o); // c
// 验证集合是否包含指定的键K
boolean b = hashMap.containsKey("2");
System.out.println(b); // true
// 验证集合是否包含指定的值V
boolean b1 = hashMap.containsValue("a");
System.out.println(b1); // true
// 移除指定键
hashMap.remove("3");
System.out.println(hashMap); // {1=b, 2=c, 4=d, 5=a}
// 获取集合里所有的键K
Set set = hashMap.keySet();
System.out.println(set); // [1, 2, 4, 5]
// 获取集合里所有的值V
Collection values = hashMap.values();
System.out.println(values); // [b, c, d, a]
// 将集合指定键K的指定的旧值替换为新的值,如果指定的旧值和集合内的旧值不一致就不会替换
hashMap.replace("5", "a", "e");
System.out.println(hashMap); // {1=b, 2=c, 4=d, 5=e}
// 将集合指定键K的值替换为指定的值V,没限制,直接就替换了
hashMap.replace("5", "f");
System.out.println(hashMap); // {1=b, 2=c, 4=d, 5=f}
// 清空集合
hashMap.clear();
System.out.println(hashMap); // {}
}
LinkedHashMap
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>{}
LinkedHashMap继承了HashMap,实现了Map接口
LinkedHashMap是HashMap的子类,自然LinkedHashMap也就继承了HashMap中所有非私有的方法。
底层数据结构是数组加链表,可以认为他是HashMap和LinkedList的合体。
特点
- 有序的(可以这么认为它的出现是解决Map集合无序的问题)
- 可指定排序方式
核心方法(常用API)
既然继承与HashMap,那HashMap只要不是私有的方法,那LinkedHashMap是都有的。
Hashtable
public class Hashtable<K,V> extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable {}
Hashtable继承Dictionary,实现Map、Cloneable、Serializable接口。
和HashMap类似,都是KV结构存储的。
就不着重介绍了,其常用的API也都相似。
TreeMap
public class TreeMap<K,V> extends AbstractMap<K,V>
implements NavigableMap<K,V>, Cloneable, java.io.Serializable{}
TreeMap继承AbstractMap,实现NavigableMap、Cloneable、Serializable接口。
TreeMap是Map的实现类。
TreeMap继承AbstractMap,是一个Map也就是一个KV结构集合
底层数据结构是红黑树来实现的
特点
- 有序的K V集合
- 支持排序(自然排序,比较器排序)
核心方法(常用API)
public static void main(String[] args) {
// 创建一个TreeMap集合
TreeMap treeMap = new TreeMap();
// 往集合添加键值。有序的 会按照键来排序
treeMap.put("2","a");
treeMap.put("4","b");
treeMap.put("3","c");
treeMap.put("1","d");
System.out.println(treeMap); // {1=d, 2=a, 3=c, 4=b}
HashMap hashMap = new HashMap();
hashMap.put("5","f");
hashMap.put("0","0");
// 往集合添加一个map集合
treeMap.putAll(hashMap);
System.out.println(treeMap); // {0=0, 1=d, 2=a, 3=c, 4=b, 5=f}
// 获取集合长度
int size = treeMap.size();
System.out.println(size); // 6
// 验证集合是否为空
boolean empty = treeMap.isEmpty();
System.out.println(empty); // false
// 获取集合指定键K的值V
Object o = treeMap.get("2");
System.out.println(o); // a
// 验证集合是否包含指定键K
boolean b = treeMap.containsKey("3");
System.out.println(b); // true
// 验证集合是否包含指定值V
boolean b1 = treeMap.containsValue("b");
System.out.println(b1); // true
// 获取集合第一个键K
Object o1 = treeMap.firstKey();
System.out.println(o1); // 0
// 获取集合最后一个键K
Object o2 = treeMap.lastKey();
System.out.println(o2); // 5
// 移除指定键的值,并返回这个值
Object remove = treeMap.remove("1");
System.out.println(remove); // d
// 获取集合第一个KV结构元素
Map.Entry entry = treeMap.firstEntry();
System.out.println(entry); // 0=0
// 获取集合最一个KV结构元素
Map.Entry entry1 = treeMap.lastEntry();
System.out.println(entry1); // 5=f
// 将集合指定键K的指定值V进行替换,如果指定的值与集合内的值不一致,则不替换
treeMap.replace("0","0","1");
System.out.println(treeMap); // {0=1, 2=a, 3=c, 4=b, 5=f}
// 将集合指定键K的指定值V进行替换,直接替换
treeMap.replace("0","2");
System.out.println(treeMap); // {0=2, 2=a, 3=c, 4=b, 5=f}
// 清空集合
treeMap.clear();
System.out.println(treeMap); // {}
}
TreeMap同TreeSet一样有一个比较坑的地方。
就是在声明Map集合时,指定的键类型没有实现Comparable接口,重写compareTo()方法。那么同样会出现异常。
怎么解决呢?和TreeSet的解决方法一样。
总结
Map是键值对映射的接口
HashMap底层是通过散列表实现的,是比较常用的,Key是通过hashCode值来存储数据的。可直接根据K获取V,访问速度很快。只允许一个K为null,V可以多个null。线程不安全,效率高。
Hashtable与HashMap类似,唯一不同的就是Hashtable的K和V都不能为null。写入速度慢。线程安全的,效率低。
TreeMap底层是通过红黑树实现的,能够把进行存储的数据按照K进行排序,默认是按升序排序,也可以指定排序的比较器。
TreeMap不允许K为null。线程不安全,效率高。遍历时得到记录是排过序的。
LinkedHashMap底层是通过链表实现的,有序的map集合,在插入值的时候可以自定义排序方式。key和value都允许为空。线程不安全。
还是之前说的那句话,集合类这几篇文章只是对集合有个认知。如想深入了解,关注我。看源码篇》。。
纸上得来终觉浅
更深入的理解它才会得到它的心❤