文章目录
Map
一、Map集合
1. Map集合概述
java.util.Map<k,v>
集合- 特点:
Map
集合是一个双列集合,一个元素包含两个值(一个key
,一个value
)。Map
集合中的元素,key
和value
的数据类型可以相同,也可以不同。Map
集合中的元素,key
是不允许重复的,value
是可以重复的。Map
集合中的元素,key
和value
是一一对应的。
2. Map常用子类
java.util.HashMap<k,v>集合 implements Map<k,v>接口
- 特点:
HashMap
集合底层是哈希表:查询的速度特别快。JDK1.8
之前:数组 + 单向链表;JDK1.8之后
:数组 + 单向链表/红黑树(链表长度超过8):提高查询的速度。
HashMap
集合是一个无序集合,存储元素和取出元素的顺序有可能不一致。
java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
- 特点:
LinkedHashMap
集合底层是哈希表 + 链表(保证迭代的顺序);LinkedHashMap
集合是一个有序的集合,存储元素和取出元素的顺序是一致的。
- 特点:
3. Map接口中的常用方法
-
public V put(K key, V value)
把指定的键与指定的值添加到Map
集合中。- 若
Map
中该key
不存在,则插入该键值对,返回null
。 - 若
Map
中该key
存在,则替换该key
对应的value
,返回被替换的value
。
import java.util.HashMap; public class Test01 { public static void main(String[] args) { HashMap<String, Integer> hashMap = new HashMap<>(); Integer v1 = hashMap.put("朱古力", 15); System.out.println(v1); // null Integer v2 = hashMap.put("朱古力", 18); System.out.println(v2); // 15 hashMap.put("猪猪侠", 20); hashMap.put("猪猪猪", 22); System.out.println(hashMap); // {猪猪猪=22, 朱古力=18, 猪猪侠=20} } }
- 若
-
public V remove(Object key)
把指定的键所对应的键值对元素在Map
集合中删除,返回删除元素的值。- 若
Map
中该key
不存在,则返回null
。 - 若
Map
中该key
存在,则删除该键值对,返回被删除的value
。
import java.util.HashMap; public class Test02 { public static void main(String[] args) { HashMap<String,Integer> hashMap = new HashMap<>(); hashMap.put("朱古力", 18); hashMap.put("猪猪侠", 20); hashMap.put("猪猪猪", 22); System.out.println(hashMap); // {猪猪猪=22, 朱古力=18, 猪猪侠=20} Integer v1 = hashMap.remove("zhuguli"); System.out.println(v1); // null Integer v2 = hashMap.remove("朱古力"); System.out.println(v2); // 18 System.out.println(hashMap); // {猪猪猪=22, 猪猪侠=20} } }
- 若
-
public V get(Object key)
根据指定的键,在Map
集合中获取对应的值。- 若
Map
中该key
不存在,则返回null
。 - 若
Map
中该key
存在,则返回该key
对应的value
。
import java.util.HashMap; public class Test03 { public static void main(String[] args) { HashMap<String,Integer> hashMap = new HashMap<>(); hashMap.put("朱古力", 18); hashMap.put("猪猪侠", 20); hashMap.put("猪猪猪", 22); System.out.println(hashMap); // {猪猪猪=22, 朱古力=18, 猪猪侠=20} Integer v1 = hashMap.get("zhuguli"); System.out.println(v1); // null Integer v2 = hashMap.get("朱古力"); System.out.println(v2); // 18 System.out.println(hashMap); // {猪猪猪=22, 朱古力=18, 猪猪侠=20} } }
- 若
-
boolean containsKey(Object key)
判断集合中是否包含指定的键。- 若
Map
中该key
不存在,则返回false
。 - 若
Map
中该key
存在,则返回该true
。
import java.util.HashMap; public class Test04 { public static void main(String[] args) { HashMap<String,Integer> hashMap = new HashMap<>(); hashMap.put("朱古力", 18); hashMap.put("猪猪侠", 20); hashMap.put("猪猪猪", 22); System.out.println(hashMap); // {猪猪猪=22, 朱古力=18, 猪猪侠=20} boolean v1 = hashMap.containsKey("zhuzhuzhu"); System.out.println(v1); // false boolean v2 = hashMap.containsKey("朱古力"); System.out.println(v2); // true System.out.println(hashMap); // {猪猪猪=22, 朱古力=18, 猪猪侠=20} } }
- 若
4. Map集合遍历键找值方式
Map
集合中的方法:Set<K> keySet()
返回此映射中包含的键的Set
视图。- 步骤:
- 使用
Map
集合中的方法keySet()
把Map
集合中所有的key
取出来,存储到一个Set
集合中; - 遍历
Set
集合,获取Map
集合中的每一个key
; - 通过
Map
集合中的方法get(key)
,找到value
。
- 使用
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class Test {
public static void main(String[] args) {
HashMap<String,Integer> hashMap = new HashMap<>();
hashMap.put("朱古力", 18);
hashMap.put("猪猪侠", 20);
hashMap.put("猪猪猪", 22);
// 获取所有的key
Set<String> set = hashMap.keySet();
// 使用迭代器
Iterator<String> it = set.iterator();
while (it.hasNext()){
String key = it.next();
Integer value = hashMap.get(key);
System.out.println(key + " = " + value);
}
// 使用增强for循环
for (String key : set) {
Integer value = hashMap.get(key);
System.out.println(key + " = " + value);
}
}
}
5. 使用Entry键值对对象遍历Map
Map
集合中的方法:Set<Map.Entry<K,v>> entrySet()
返回此映射中包含的映射关系的Set
视图。- 步骤:
- 使用
Map
集合中的方法entrySet()
,把Map
集合中多个Entry
对象取出来,存储到一个Set
集合中; - 遍历
Set
集合,获取每一个Entry
对象; - 使用
Entry
对象中的方法getKey()
和getValue()
获取键与值。
- 使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AXpKp4De-1589461055259)(https://raw.githubusercontent.com/zhugulii/picBed/master/Map%E9%9B%86%E5%90%88%E9%81%8D%E5%8E%86%E9%94%AE%E5%80%BC%E5%AF%B9%E6%96%B9%E5%BC%8F.jpg)]
public class Test {
public static void main(String[] args) {
HashMap<String,Integer> hashMap = new HashMap<>();
hashMap.put("朱古力", 18);
hashMap.put("猪猪侠", 20);
hashMap.put("猪猪猪", 22);
//获取所有的entry键值对对象
Set<Map.Entry<String, Integer>> entry = hashMap.entrySet();
//使用迭代器
Iterator<Map.Entry<String, Integer>> it = entry.iterator();
while (it.hasNext()) {
Map.Entry<String, Integer> info = it.next();
String key = info.getKey();
Integer value = info.getValue();
System.out.println(key + "=" + value);
}
//使用增强for循环
for (Map.Entry<String, Integer> info : entry) {
String key = info.getKey();
Integer value = info.getValue();
System.out.println(key + "=" + value);
}
}
}
6. HashMap存储自定义类型键值
Map
集合保证key
是唯一的:作为key
的元素,必须重写hashCode()
方法和equals()
方法。
import java.util.Objects;
public class Person {
private String name;
private int age;
//覆盖重写equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
//覆盖重写hashCode方法
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//覆盖重写toString方法
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.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;
}
}
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test {
public static void main(String[] args) {
demo01(); // 上海-->Person{name='猪猪猪', age=22}
// 西安-->Person{name='巧克力', age=24}
// 北京-->Person{name='猪猪侠', age=20}
demo02(); // Person{name='猪猪猪', age=22}-->上海
// Person{name='朱古力', age=18}-->杭州
// Person{name='猪猪侠', age=20}-->北京
}
private static void demo01() {
HashMap<String,Person> hashMap = new HashMap<>();
hashMap.put("西安",new Person("朱古力",18));
hashMap.put("北京",new Person("猪猪侠",20));
hashMap.put("上海",new Person("猪猪猪",22));
hashMap.put("西安",new Person("巧克力",24));
//使用keySet和增强for遍历集合
Set<String> set = hashMap.keySet();
for(String key : set) {
Person value = hashMap.get(key);
System.out.println(key + "-->" + value);
}
}
private static void demo02() {
HashMap<Person,String> hashMap = new HashMap<>();
hashMap.put(new Person("朱古力",18),"西安");
hashMap.put(new Person("猪猪侠",20),"北京");
hashMap.put(new Person("猪猪猪",22),"上海");
hashMap.put(new Person("朱古力",18),"杭州");
//使用entrySet与增强for遍历集合
Set<Map.Entry<Person, String>> set = hashMap.entrySet();
for (Map.Entry<Person,String> entry : set) {
Person key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "-->" + value);
}
}
}
7. LinkedHashMap集合
java.util.LinkedHashMap<K,V> extends HashMap<K,V>
Map
接口的哈希表和链接列表实现,具有可预知的迭代顺序。- 底层原理:哈希表 + 链表(记录元素的顺序)。
import java.util.HashMap;
import java.util.LinkedHashMap;
public class Test {
public static void main(String[] args) {
HashMap<String,String> hashMap = new HashMap<>();
hashMap.put("a","1");
hashMap.put("c","2");
hashMap.put("d","3");
hashMap.put("b","4");
System.out.println(hashMap); // {a=1, b=4, c=2, d=3} 无序
LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("a","1");
linkedHashMap.put("c","2");
linkedHashMap.put("d","3");
linkedHashMap.put("b","4");
System.out.println(linkedHashMap); // {a=1, c=2, d=3, b=4} 有序
}
}
8. HashTable集合
java.util.Hashtable<K,V>集合 implements Map<K,V>接口
HashMap:
- 底层是一个哈希表,是一个线程不安全的集合,是多线程集合,速度快。
- 可以存储
null
值,null
键。
Hashtable:
- 底层是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢。
- 不可以存储
null
值,null
键。
HashTable
和Vector
集合一样,在JDK1.2
之后被更先进的集合(HashMap
,ArrayList
)取代了。Hashtable
的子类Properties
依然活跃,且Properties
集合是唯一和IO
流相结合的集合。
import java.util.HashMap;
import java.util.Hashtable;
public class Test {
public static void main(String[] args) {
HashMap<String,String> hashMap = new HashMap<>();
hashMap.put(null,"a");
hashMap.put("b",null);
hashMap.put(null,null);
System.out.println(hashMap); // {null=null, b=null}
Hashtable<String,String> hashtable = new Hashtable<>();
hashtable.put(null,"a");
hashtable.put("b",null);
hashtable.put(null,null);
System.out.println(hashtable); // 空指针异常:NullPointerException
}
}
9. 一个小练习
//计算一个字符串中每个字符出现的次数
import java.util.HashMap;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// 获取字符串
System.out.println("请输入一个字符串:"); // aaabbbcccabc
Scanner sc = new Scanner(System.in);
String str = sc.next();
//遍历每一个字符,计算出现的次数并存入HashMap中
HashMap<Character,Integer> hashMap = new HashMap<>();
for(int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (!hashMap.containsKey(ch)) {
hashMap.put(ch, 1);
} else {
int count = hashMap.get(ch) + 1;
hashMap.put(ch,count);
}
}
//输出
System.out.println(hashMap); // {a=4, b=4, c=4}
}
}
二、JDK9
对集合添加的优化
JDK9
的新特性:List
接口、Set
接口、Map
接口,里边增加了一个静态的方法of
,可以给集合一次性添加多个元素。static<E> List<E> of (E...elements)
- 使用前提:当集合中存储的元素个数已经确定了,不再改变时使用。
- 注意:
of
方法只适用于List
接口、Set
接口、Map
接口,不适用于接口的实现类。of
方法返回值是一个不能改变的集合,集合不能再使用add
、put
方法添加元素,会抛出异常。Set
接口、Map
接口在调用of
方法的时候,不能有重复的元素,否则会抛出异常。
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Test {
public static void main(String[] args) {
List<Integer> list = List.of(1,2,3,4,5,6);
System.out.println(list); // [1, 2, 3, 4, 5, 6]
//list.add(10); // UnsupportedOperationException 不支持的操作异常
Set<Integer> set = Set.of(1,2,3);
System.out.println(set); // [3, 2, 1]
//set.add(4); // UnsupportedOperationException
//Set<Integer> set1 = Set.of(1,2,1); // IllegalArgumentException非法参数异常
Map<Character,Integer> map = Map.of('a',1,'b',2);
System.out.println(map); // {a=1, b=2}
//map.put('c',3); // UnsupportedOperationException
Map<Character,Integer> map1 = Map.of('a',1,'b',2,'a',3); // IllegalArgumentException
}
}