B站 韩顺平 老师课程的笔记

Map接口

常用Map接口实现类

  1. HashMap
  2. Hashtable
  3. Properties

HashMap小结

  • HashMap是Map接口使用频率最高的实现类
  • HashMap是以key-value对的方式来储存数据
  • key不能重复,但是值可以重复,允许使用null键和null值
  • 如果添加相同的key,则会覆盖原来的key-value,等同于修改(key不会替换,val会替换)
  • 与HashSet一样,不能保证映射的顺序,因为底层是以hash表的方式来储存的(jdk8的hashMap底层是 数组+链表+红黑树)
  • HashMap没有实现同步,因此是线程不安全的

Map接口实现类 都有的特点

以HashMap举例:

  1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(无序)
  2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  3. Map中的key不允许重复,原因和HashSet一样(前面分析过源码)
  4. Map中的key可以为null,value也可以为null,注意,key为null,只能有一个,value为null,可以为多个
  5. 常用String类作为Map的key
  6. key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
  7. 一对k-v是放在一个HashMap$Node中的,因为Node实现了Entry的接口,有些书也说 一对k-v就是一个Entry
    自我总结:key影响位置,value是值,key相等表示在同一个位置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class Map_ {
public static void main(String[] args) {
// 1. Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value(无序)
Map map = new HashMap();
map.put("no.1","牛逼");
map.put("no.2","牛人");
System.out.println("map= " + map);

// 2. Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中

// 3. Map中的key不允许重复,原因和HashSet一样(前面分析过源码)
map.put("no.1","小狗");
System.out.println("map= " + map);//可以看出当key相等的时候就相当于是替换value

// 4. Map中的key可以为null,value也可以为null,注意,key为null,只能有一个,value为null,可以为多个
map.put(null,"小牛");
map.put(null,null);
map.put("no.3",null);
System.out.println("map= " + map);//因为多个key为null,既然都是null那么这几个的位置都相同,就会被替换

// 5. 常用String类作为Map的key//本例中基本上都是用到String类作为key(key可以为任何类型)
// 6. key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
System.out.println(map.get("no.2"));//"no.2"是key,key相当于是位置,等价于数组中的下标,所以可以类似得到对应位置的值
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapSource_ {
public static void main(String[] args) {
Map map = new HashMap();
map.put("no1", "韩顺平");//k-v
map.put("no2", "张无忌");//k-v
map.put(new Car(), new Person());//k-v

//1. k-v 最后是 HashMap$Node node = newNode(hash, key, value, null)
//2. k-v 为了方便程序员的遍历,还会 创建 EntrySet 集合 ,该集合存放的元素的类型 Entry, 而一个Entry
// 对象就有k,v EntrySet<Entry<K,V>> 即: transient Set<Map.Entry<K,V>> entrySet;
//3. entrySet 中, 定义的类型是 Map.Entry ,但是实际上存放的还是 HashMap$Node
// 这时因为 static class Node<K,V> implements Map.Entry<K,V>
//4. 当把 HashMap$Node 对象 存放到 entrySet 就方便我们的遍历, 因为 Map.Entry 提供了重要方法
// K getKey(); V getValue();

Set set = map.entrySet();
System.out.println(set.getClass());// HashMap$EntrySet
for (Object obj : set) {
//System.out.println(obj.getClass()); //HashMap$Node
//为了从 HashMap$Node 取出k-v
//1. 先做一个向下转型
Map.Entry entry = (Map.Entry) obj;
System.out.println(entry.getKey() + "-" + entry.getValue() );
}
Set set1 = map.keySet();
System.out.println(set1.getClass());
Collection values = map.values();
System.out.println(values.getClass());
}
}
class Car {}
class Person{}

常用方法

方法列举

  1. put():添加
  2. remove():根据键删除映射关系
  3. get():根据键获取值
  4. size():获取元素个数
  5. isEmpty():判断个数是否为0
  6. clear():清除
  7. containsKey():查找键是否存在
  8. containsValue():查找值是否存在

代码尝试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import java.util.HashMap;
import java.util.Map;

/**
* @author 张永锐
*/
public class MapMethod_ {
public static void main(String[] args) {
//演示Map常用方法


// 1. put():添加 返回类型是Object
Map map = new HashMap();
map.put("邓超","孙俪");
map.put("牛逼","小牛人");
map.put("牛逼","大牛人");//演示替换
map.put("zyr","fengweng");
map.put(null,"单身狗");
map.put("book",new Book("无",100));
System.out.println("map= " + map);

// 2. remove():根据键删除映射关系
map.remove("邓超");//删除key为"邓超"的一对k-v
System.out.println("map= " + map);

// 3. get():根据键获取值,返回Object类型,只能是Object类型(可直接输出)
Object v = map.get(null);
System.out.println("key=null对应value: " + v);
System.out.println("key=zyr对应value: " + map.get("zyr"));

// 4. size():获取元素个数,返回值是int类型
int num = map.size();
Map map1 = new HashMap();
map1.put("测试","个数");
System.out.println("map.size() = " + num);
System.out.println("map1.size() = " + map1.size());

// 5. isEmpty():判断个数是否为0,返回值是boolean类型
// 6. clear():清除(将所有内容都删除),返回类型是void
boolean is = map.isEmpty();
map1.clear();//清空map1
System.out.println("map.isEmpty() = " + is);
System.out.println("map1.isEmpty() = " + map1.isEmpty());

// 7. containsKey():查找键是否存在,返回类型是boolean
boolean ck = map.containsKey("zyr");
System.out.println("map.containsKey(\"zyr\") = " + ck);
System.out.println("map.containsKey(\"没有的键\") = " + map.containsKey("没有的键"));

// 8.containsValue():查找值是否存在,返回类型是boolean
boolean cv = map.containsValue("fengweng");
System.out.println("map.containsValue(\"fengewng\") = " + cv);
System.out.println("map.containsVaule(\"没有的值\") = " + map.containsValue("没有的值"));
}
}
class Book {
private String name;
private int num;

public Book(String name, int num) {
this.name = name;
this.num = num;
}

@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", num=" + num +
'}';
}
}

输出展示

1
2
3
4
5
6
7
8
9
10
11
12
map= {邓超=孙俪, null=单身狗, zyr=fengweng, book=Book{name='无', num=100}, 牛逼=大牛人}
map= {null=单身狗, zyr=fengweng, book=Book{name='无', num=100}, 牛逼=大牛人}
key=null对应value: 单身狗
key=zyr对应value: fengweng
map.size() = 4
map1.size() = 1
map.isEmpty() = false
map1.isEmpty() = true
map.containsKey("zyr") = true
map.containsKey("没有的键") = false
map.containsValue("fengweng") = true
map.containsVaule("没有的值") = false

Map六大遍历方式

  1. containsKey():查找键的方式
  2. containsValue():查找值的方式
  3. keySet():获取所有值v
  4. entrySet():获取所有关系k-v
  5. values():获取所有值v
  6. key():获取所有键k

代码展示

只展示了较复杂的遍历情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.util.*;

/**
* @author 张永锐
*/
public class Map_traversal {
public static void main(String[] args) {
//将六大遍历方式

//创建待遍历map
Map map = new HashMap();
map.put("邓超","孙俪");
map.put("牛逼","牛人");
map.put("zyr","fengweng");
map.put(null,"单身狗");

// 3. keySet():获取所有值v
//先取出所有的key,通过key取出对应的value (Set)
Set kset = map.keySet();
//Set又有两种遍历方式
//(1)增强for
System.out.println("----keySet()增强for----");
for(Object o : kset){
System.out.println(o + "-" + map.get(o));
}
//(2)迭代器
System.out.println("----keySet()迭代器----");
Iterator iterator = kset.iterator();
while(iterator.hasNext()){
//System.out.println(iterator.next() + "-" + map.get(iterator.next()));//这样些有问题,两次next()
Object ob = iterator.next();
System.out.println(ob + "-" + map.get(ob));
}

// 4. entrySet():获取所有关系k-v
Set entrySet = map.entrySet();
//(1)增强for
System.out.println("----entrySet()增强for----");
for(Object entry : entrySet) {
Map.Entry m = (Map.Entry) entry;//要先转型
System.out.println(m.getKey() + "-" + m.getValue());
}
//(2)迭代器
System.out.println("----entrySet()迭代器----");
Iterator iterator2 = entrySet.iterator();
while(iterator2.hasNext()){
Object next = iterator2.next();
// System.out.println(next + "-" + map.get(next));//这一句也可输出
Map.Entry entry = (Map.Entry) next;//要先转型
System.out.println(entry.getKey() + "-" + entry.getValue());
}

// 5. values():获取所有值v
//先把所有values取出来(Collection)
Collection vcol = map.values();
//Collection有两种遍历方式
//(1)增强for
System.out.println("----values()增强for----");
for(Object o : vcol){//冒号后面其实也可以直接式map.values()
System.out.println(o + "-" + map.get(o));
}
//(2)迭代器(省略)
}
}