Map

特点:

  1. 双列集合一次要存储一对数据,分别为键和值
  2. 键不能重复,值可以重复
  3. 键和值是一一对应的,每一个键只能找到自己对应的值
  4. 键+值的整体,称之为“键值对”或者“键值对对象”,在java中叫做“Entry对象”

Map方法

  • 创建Map集合的对象
1
Map<T, T> m = new HashMap<> ();
  • 添加元素
1
2
3
4
5
Map<T, T> m = new HashMap<> ();
//put方法添加时候会有两种操作:添加/覆盖
//在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方法返回null
//在添加数据的时候,如果键存在,那么会把原有的键值对对象覆盖,方法返回被覆盖的值
m.put(t1, t2);
  • 移除所有元素
1
m.clear();
  • 判断是否包含指定的键
1
m.containsKey(t1);
  • 判断是否包含指定的值
1
m.containsValue(t2);
  • 判断集合是否为空
1
m.isEmpty();
  • 集合的长度,键值对的个数
1
m.size();
  • 获取一个键对应的值,如果键不存在于Map中,则返回一个默认值(Java 8)
1
2
3
4
//V getOrDefault(Object key, V defaultValue)
//key:你想要获取其值的键
//defaultValue:如果指定的键在Map中不存在,则返回这个默认值
int value = m.getOrDefault(t3, 0);
  • 将键与一个值合并到Map中,如果键已经存在,则根据提供的合并函数来更新该键的值
1
2
3
4
5
6
7
8
9
10
11
12
//V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V>remappingFunction)
//key:要合并的键
//value:如果键不存在,要添加到Map中的值
//remappingFunction:一个合并函数,如果键已经存在,则使用这个函数来计算新值。该函数接收两个参数,第一个是键当前对应的值,第二个是要合并的值

Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);

// 合并值,如果键不存在则添加
map.merge("c", 3, Integer::sum); // "c"不存在,所以添加"3"
map.merge("a", 10, Integer::sum); // "a"存在,所以将1和10相加得到11
  • 计算键的值,如果键不存在于Map中,则使用提供的映射函数来计算其值,并将其插入到Map中
1
2
3
4
5
6
7
8
9
10
11
12
13
//V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) 
//key:要计算的值
//mappingFunction:如果键不存在,使用这个函数来计算键的值

Map<String, Integer> map = new HashMap<>();
map.put("a", 1);
map.put("b", 2);

// 如果键不存在,则使用提供的函数计算值并插入
map.computeIfAbsent("c", k -> k.length()); // "c"不存在,所以计算其长度并插入
map.computeIfAbsent("a", k -> k.length()); // "a"存在,所以不做任何操作

System.out.println(map); // 输出 {a=1, b=2, c=1}

遍历方法

键找值

将键找出来单独放到单列集合中,通过遍历键来得到值

  • 迭代器遍历
1
2
3
4
5
6
7
Map<T, T> map = new HashMap<> ();
Set<T> keys = map.keySet();
Iterator<T> iterator = keys.iterator();
while (iterator.hasNext()) {
T key = iterator.next();
T value = map.get(key);
}
  • 增强for遍历
1
2
3
4
5
Map<T, T> map = new HashMap<> ();
Set<T> keys = map.keySet();
for (T key : keys) {
T value = map.get(key);
}
  • lambda表达式
1
2
3
4
5
6
Map<T, T> map = new HashMap<> ();
Set<T> keys = map.keySet();
keys.forEach(key -> {
T value = map.get(key);
System.out.println(value);
});

键值对

  • 迭代器遍历
1
2
3
4
5
6
7
8
Map<T, T> map = new HashMap<> ();
Set<Map.Entry<T, T>> entries = map.entrySet();
Iterator<Map.Entry<T, T>> iterator = entries.iterator();
while (iterator.hasNext()) {
Map.Entry<T,T> entry = iterator.next();
T key = entry.getKey();
T value = entry.getValue();
}
  • 增强for遍历
1
2
3
4
5
6
Map<T, T> map = new HashMap<> ();
Set<Map.Entry<T, T>> entries = map.entrySet();
for (Map.Entry<T, T> entry : entries) {
T key = entry.getKey();
T value = entry.getValue();
}
  • lambda表达式
1
2
3
4
5
6
Map<T, T> map = new HashMap<> ();
Set<Map.Entry<T, T>> entries = map.entrySet();
entries.forEach(entry -> {
T key = entry.getKey();
T value = entry.getValue();
});

lambda表达式

1
2
3
4
Map<T, T> map = new HashMap<> ();
map.forEach((T key, T value) -> {
System.out.println(key + "=" + value);
});

HashMap

  • HashMap底层是哈希表结构
  • 依赖hashCode方法和equals方法保证键的唯一
  • 如果键存储的是自定义对象,需要重写hashCode和equals方法,如果值是自定义对象,则不需要

LinkedHashMap

  • LinkedHashMap底层依旧是哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序
  • 保证了存储和取出的顺序一致

TreeMap

  • TreeMap的底层原理和TreeSet一样,都是红黑树结构
  • 输出时会将键默认按照升序排列(可以通过实现Comparable接口或者创建对象时传递Comparator比较器对象来指定比较规则)

例:如何想要按照降序排列,可以在创建对象的时候传递比较器Comparator对象

1
2
3
4
5
6
TreeMap<Integer, String> tm = new TreeMap<> (new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});