Map集合
java.util.Map<K, V>
是一个接口
Map不是Collection的子接口,二者无关。
- 第一个泛型代表:键是什么类型。
- 第二个泛型代表:值是什么类型。
二者可以相同,也可以不同
里面的方法是一对儿一对儿的数据,也叫作键值对儿。
特点:
- 1、键不可以重复
- 2、值可以重复
- 3、根据键可以找到对应的值
每一对儿元素,就是一个Entry对象。
Entry是Map的一个内部子类接口。
Map的常用实现类有:
1、HashMap:HashSet底层就是在复用HashMap。里面也是哈希表,速度特别快。
2、LinkedHashMap:底层也是哈希表,但是额外还有链表,从而维护顺序。
3、TreeMap:带有键的大小排序功能。
注意事项:
由于Map当中的key不能重复,那么就要考虑怎么确定元素对象那个是否重复?
确定两个对象是一样还是不一样:有equals和HashCode方法决定。
常用方法:
public V put(K key, V value )
: 添加一个键对儿,返回被替换的本来value值。
public V remove(Object key )
: 根据键删除对应的键值对儿,返回value值。
public V get(Object key )
: 根据键,获取对应的value值。
public Set<K> keySet()
: 获取所有的键集合。
public Collection(V) value()
: 获取所有的值。
遍历Map集合的两种方式:
1、keySet(): 获取所有的键,然后再根据键获取值get方法。
2、entrySet(): 直接获取所有别的键值对儿。
Map接口当中有一个内部接口:Map.Entry<K, v>
一个Entry就代表一个键值对儿,好比是一个结婚证。
public Set<结婚证> entrySet(): 获取所有的结婚证
public Set<Entry> entrySet()
:
public Set<Map.Entry> entrySet()
:
public Set<Map.Entry<男方,女方>> entrySet()
:
public Set<Map.Entry<K,V>> entrySet()
:
可以通过entrySet方法一次性获取所有的键值对儿
- 1、得到所有的键值对儿:entrySet方法
- 2、根据键值对儿,获取键:getKey方法
- 3、根据键值对儿,获取值:getValue方法
Entry<K, V>
接口当中定义的常用方法:
public K getKey()
: 获取键
public K getValue()
: 获取值
// 第一个泛型代表学号
// 第二个泛型代表姓名
Map<String ,String> map = new HashMap<>();
// 添加元素用put方法
map.put("123","周星驰");
map.put("124","周博通");
map.put("125","周润发");
String s = map.put("126", "周润发");
System.out.println(s); // 返回的原来的结果,而原来没有,所以为null
Set<String> strings = map.keySet(); // 获取所有的键值集合。
for (String string : strings) {
System.out.println(string+"-"+map.get(string)); // 根据键值获取value值
}
String remove1 = map.remove("123");
System.out.println("删除的是:"+remove1); // 删除的是:周星驰
String remove2 = map.remove("100");
System.out.println(remove2); // null ,没有键值为100的数据,所以返回null
// 通过entrySet一下获取所有的键值对儿
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"-"+value);
}
注意事项:
- 如果自定义的类型,当成Map里面的value使用,那么没有任何要求。Value可以重复。
如果自定义的类型,当做Map里面的key使用,那么key不可以重复,就必须要覆盖重写equals和hashCode。
public static void main(String[] args) {
Map<Integer,Student> mapA = new HashMap<>();
mapA.put(001,new Student("迪丽热巴",18));
mapA.put(002,new Student("古力娜扎",28));
mapA.put(003,new Student("马尔扎哈",38));
mapA.put(004,new Student("马尔扎哈",38));
// {1=Student{name='迪丽热巴', age=18}, 2=Student{name='古力娜扎', age=28}, 3=Student{name='马尔扎哈', age=38}, 4=Student{name='马尔扎哈', age=38}}
System.out.println(mapA); // 4对儿
Map<Student ,Integer> mapB = new HashMap<>();
mapB.put(new Student("迪丽热巴",18),001);
mapB.put(new Student("古力娜扎",28),002);
mapB.put(new Student("马尔扎哈",38),003);
mapB.put(new Student("马尔扎哈",38),004);
// 如果补充些equals和hashCode方法,依然输出四队,而键值是不能重复的,所以Student要重写equals和hashCode方法
System.out.println(mapB);
}
LinkedHashMap
java.util.LinkedHashMap
是HashMap的子类
里面可有哈希表,速度也比较外,但是额外还有链表,专门用来维护顺序。
public static void main(String[] args) {
Map<String, String> map = new LinkedHashMap<>();
map.put("AAA", "张无忌");
map.put("bbb", "张三丰");
map.put("ccc", "张翠山");
Set<Map.Entry<String, String>> entries = map.entrySet();
for(Map.Entry<String, String> entry : entries){
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"--"+value);
}
}
- 1、看get方法的返回值是不是nul
2、containsKey方法可以直接判断是否包含键。得到boolean值。
getOrDefault方法:获取键对应的值;如果没有,那么返回第二个参数,代表默认值。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String next = sc.next();
// 方法一:
// 定义一个map集合用来计算字符个数
Map<Character, Integer> map = new HashMap<>();
char[] chars = next.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (map.containsKey(chars[i])) {
int num = map.get(chars[i]);
num++;
map.put(chars[i], num);
} else {
map.put(chars[i], 1);
}
}
System.out.println(map);
System.out.println("================");
// 方法二
Map<Character, Integer> mapB = new HashMap<>();
for (int i = 0; i < next.length(); i++) {
// 将字符串转换个单个字符
char ch = next.charAt(i);
// 如果有,那么返回对应的value值,第二个参数没用。
// 如果没有,那么直接返回第二个参数,代表默认值。
int num2 = mapB.getOrDefault(ch, 0);
mapB.put(ch, ++num2);
}
System.out.println(mapB);
}
TreeSet:
带有大小排序的功能。
TreeMap:
其中的键带有大小排序的功能。
下面两个概念要注意区分:
先后顺序,时间上先来后到。
大小排序:谁大谁小,从小到大
下面两种比较也要区分:
一不一样(相同比较器):由equals和hashCode决定。
谁大谁小(大小比较器):由Comparable或者外部指定的Comparator接口决定。
注意事项:
如果使用自定义的类型做键值,需要再自定义的类实现Coparable接口。
public static void main(String[] args) {
// Set本身加入的元素是无序的,而TreeSet带有大小排序
Set<String> set = new TreeSet<>();
set.add("AAA");
set.add("DDD");
set.add("BBB");
set.add("CCC");
System.out.println(set); // [AAA, BBB, CCC, DDD]
System.out.println("===========");
// TreeMap键值大小排序功能
Map<String, String> map = new TreeMap<>();
map.put("aaa", "bbb");
map.put("ggg", "bbb");
map.put("eee", "bbb");
map.put("sss", "bbb");
System.out.println(map); // {aaa=bbb, eee=bbb, ggg=bbb, sss=bbb}
// 运用TreeMap把自定义的对象作为键值进行大小排序
Map<Person, String> map2 = new TreeMap<>();
map2.put(new Person("鹿晗", 24), "shit");
map2.put(new Person("吴亦凡", 23), "shit");
// 如果Person不去继承Comparable类设置大小关系,会报 :ClassCastException
Set<Map.Entry<Person,String>> entries = map2.entrySet();
for (Map.Entry<Person, String> entry : entries) {
Person key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"--"+value);
}
}
静态方法of:
从Java9开始,集合的接口当中添加了静态方法of,用来快速生成集合
注意事项:
通过这种方式创建出来的集合,是不可变集合。
如果尝试改变集合当中的内容,那么会发生:UnsuporttedOperationException。
public static void main(String[] args) {
List<String> list = List.of("java", "groovy", "kotlin", "scala");
// list.add("php"); // UnsupportedOperationException
System.out.println(list); // [java, groovy, kotlin, scala]
// 对于Set集合来说,如果有重复元素,将会发生IllegalArgumentException异常。
Set<String> set = Set.of("java", "groovy", "kotlin"/*,"java"*/);
System.out.println(set); // [groovy, kotlin, java]
Map<String, String> map = Map.of("王宝强", "马蓉", "贾乃亮", "李小璐");
System.out.println(map); // {王宝强=马蓉, 贾乃亮=李小璐}
}
Map集合的概述
Entry的概念
Map统计字符出现的顺序
斗地主的排序案例分析