一、Map集合
(一)概述
1、Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
2、Map集合中的元素,key和value的数据类型可以相同也可以不同
3、Map集合中的元素,key是不允许重复的,value是可以重复的
4、Map集合中的元素,key和value是一一对应的。
(二)Map常用子类
HashMap集合
java.util.HashMap<k,v> 集合 implements Map<k,v>接口
- 特点
1、HashMap的集合底层是哈希表:查询速度非常快
jdk1.8之前:数组+单向链表
jdk1.8之后:数组+单向链表/红黑树(链表的长度超过8):提高查询的速度
2、HashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
LinkedHashMap集合
java.util.LinkedHashMap<k,v> 集合 extends HashMap<k,v>集合
- 特点
1、LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)
2、LInkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
(三)Map接口中常用的方法
-
public V put(K key,V value):把指定的键与指定的集合添加到Map集合中 返回值:v 存储键值对的时候,key不重复,返回值是null 存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值
private static void show01() {
Map<String, Integer> map1 = new HashMap<>();
String s1= String.valueOf(map1.put("zhangsan",18));
System.out.println(s1);
String s2= String.valueOf(map1.put("zhangsan",20));
System.out.println(s2);
System.out.println(map1);
map1.put("lisi",20);
map1.put("wangmazi",22);
map1.put("zhaosi",25);
System.out.println(map1);
}
null
18
{zhangsan=20}
{lisi=20, zhaosi=25, zhangsan=20, wangmazi=22}
-
public V remove(Object key):把指定键所对应的键值对元素在Map集合中删除,返回被删除元素的值 返回值:v key存在,v返回被删除的值 key不存在,返回null
private static void show02() {
Map<String,Integer> map2 =new HashMap<>();
map2.put("math",67);
map2.put("Englishi",79);
map2.put("history",81);
System.out.println(map2);
Integer v1=map2.remove("math");
System.out.println("v1:"+v1);
Integer v2 =map2.remove("PE");
System.out.println("v2:"+v2);
}
{math=67, history=81, Englishi=79}
v1:67
v2:null
-
public V get(Object key) :根据指定的键在Map集合中获取对应的值 返回值: key存在,返回对应的value值 key不存在,返回null
private static void show03() {
Map<String,Integer> map2 =new HashMap<>();
map2.put("math",67);
map2.put("Englishi",79);
map2.put("history",81);
System.out.println(map2);
Integer v1=map2.get("math");
System.out.println("v1:"+v1);
Integer v2 =map2.get("PE");
System.out.println("v2:"+v2);
}
{math=67, history=81, Englishi=79}
v1:67
v2:null
-
boolean containsKey(Object key):判断集合中是否包含指定的键 包含返回true,不包含返回false
private static void show04() {
Map<String,Integer> map2 =new HashMap<>();
map2.put("math",67);
map2.put("Englishi",79);
map2.put("history",81);
System.out.println(map2);
boolean b1 =map2.containsKey("math");
System.out.println("b1:"+b1);
boolean b2 =map2.containsKey("PE");
System.out.println("b2:"+b2);
}
b1:true
b2:false
(四)Map集合遍历键找值的方式
- 通过元素中的键,获取键对应的值
- 对应方法
Set<K> keySet() :返回此映射包含的键的Set视图
1、实现步骤
- 使用Map集合中的方法keySet(),把Map集合所有的key取出来存储到一个set集合中
- 遍历set集合,获取Map集合中的每一个key值
- 通过Map集合中的方法get(key),通过key找到value
2、代码实现
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class m2 {
public static void main(String[] args) {
Map<String,Integer> map =new HashMap<>();
map.put("math",67);
map.put("Englishi",79);
map.put("history",81);
System.out.println(map);
Set<String> set = map.keySet();
//使用迭代器遍历
Iterator it = set.iterator();
while(it.hasNext()){
String s1= (String) it.next();
Integer v1=map.get(s1);
System.out.println(s1+"="+v1);
}
System.out.println("========================================");
for (String s2 : set) {
Integer v2=map.get(s2);
System.out.println(s2+"="+v2);
}
}
}
{math=67, history=81, Englishi=79}
math=67
history=81
Englishi=79
========================================
math=67
history=81
Englishi=79
(五)Entry键值对对象
1、概述
2、Map集合遍历键值对的方式
- 使用Entry对象遍历
- 实现步骤
- 使用Map集合中的entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
- 遍历Set集合,获取每一个Entry对象
- 使用Entry对象中的方法getKey()和getValue()获取键和值
import java.util.*;
public class m3 {
public static void main(String[] args) {
Map<String,Integer> map =new HashMap<>();
map.put("zhangsan",18);
map.put("lisi",20);
map.put("wangwu",19);
Set<Map.Entry<String,Integer>> set = map.entrySet();
//使用迭代器遍历
Iterator<Map.Entry<String,Integer>> it =set.iterator();
while(it.hasNext()){
Map.Entry<String,Integer> entry = it.next();
String key = entry.getKey();
int value = entry.getValue();
System.out.println(key+"="+value);
}
System.out.println("==========================================");
//使用增强for
for (Map.Entry<String,Integer> entry:
set) {
System.out.println(entry);
}
}
}
lisi=20
zhangsan=18
wangwu=19
==========================================
lisi=20
zhangsan=18
wangwu=19
(六)、HashMap存储自定义类型键值
- Map集合保证key是唯一的,作为key的元素,必须重写hashcode和equals方法以保证key唯一
import java.util.Objects;
public class person {
private String name;
private int age;
public person() {
}
public person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof person)) return false;
person person = (person) o;
return getAge() == person.getAge() &&
getName().equals(person.getName());
}
@Override
public int hashCode() {
return Objects.hash(getName(), getAge());
}
@Override
public String toString() {
return "person{" +
"name='" + name + '\'' +
", 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 p {
public static void main(String[] args) {
show01();
System.out.println("=======================================");
show02();
}
private static void show02() {
/*key:person类型
为保证key的唯一性必须重写hashcode和equals方法
value:String类型
可以重复
*/
HashMap<person,String> map2 =new HashMap<>();
map2.put(new person("zhaoliu",89),"china");
map2.put(new person("zhouqi",69),"china");
map2.put(new person("Alice",89),"England");
map2.put(new person("zhaoliu",89),"china");
Set<Map.Entry<person,String>> set = map2.entrySet();
for (Map.Entry<person, String> e :
set) {
System.out.println(e);
}
}
private static void show01() {
/*key:String类型
String重写了hashcode和equals方法可以保证key唯一
value:person类型
value可以重复
*/
HashMap<String,person> map1= new HashMap<>();
map1.put("xian",new person("zhangsan",18));
map1.put("shanghai",new person("wangmaizi",19));
map1.put("beijing",new person("wangwu",20));
map1.put("xian",new person("lisi",18));//为保证key唯一性,会将新的key取代旧的key值
Set<String> set1 =map1.keySet();
for (String key:
set1) {
person value = map1.get(key);
System.out.println(key + "->" + value);
}
}
}
xian->person{name='lisi', age=18}
shanghai->person{name='wangmaizi', age=19}
beijing->person{name='wangwu', age=20}
=======================================
person{name='zhaoliu', age=89}=china
person{name='Alice', age=89}=England
person{name='zhouqi', age=69}=china
Process finished with exit code 0
(七)、LinkedHashMap
- LinkedHashMap是HashMap的子类。底层原理是:哈希表+链表(记录元素的顺序)
import java.util.HashMap;
import java.util.LinkedHashMap;
public class linke {
public static void main(String[] args) {
HashMap<String,Integer> map =new HashMap<>();
map.put("a",1);
map.put("c",3);
map.put("b",2);
System.out.println(map);
//无序
LinkedHashMap<String,Integer> linked = new LinkedHashMap<>();
linked.put("a",1);
linked.put("c",3);
linked.put("b",2);
System.out.println(linked);
//有序
}
}
{a=1, b=2, c=3}
{a=1, c=3, b=2}
(八)Hashtable集合
- 实现了Map接口
- HashMap和Hashtable的区别
- HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快。(之前的所有集合)可以存储null值,null键。
- Hashtable集合:底层是一个哈希表,是一个线程安全的集合,是单线程的集合,速度慢。不能存储null键和值
- Hashtable和Vector集合在Jdk1.2版本后被取代(HashMap,ArrayList)
Map集合练习:计算一个字符中每个字符出现的次数
import java.util.HashMap;
import java.util.Scanner;
//获取字符串中每一个字符出现的次数
public class Stringcount {
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
System.out.println("请输入字符串:");
String str =sc.next();
HashMap<Character,Integer> map =new HashMap<>();
for (char c:
str.toCharArray()) {
if(map.containsKey(c)){
Integer value = map.get(c);
value++;
map.put(c,value);
}else{
map.put(c,1);
}
}
for (char key:
map.keySet()) {
Integer value = map.get(key);
System.out.println(key+"="+value);
}
}
}
请输入字符串:
dsklfjkslfks
s=3
d=1
f=2
j=1
k=3
l=2
二、集合中知识点的补充
(一)JDK9对集合添加的优化
- List接口,Set接口,Map接口中新增了一个静态的方法of,可以给集合一次性添加多个元素
- 使用前提:
当集合中存储的元素个数已经确定,不再改变时使用
- 注意:
- of方法只适用于List接口,Set接口,Map接口,不适用于接口的实现类
- of方法的返回值是一个不能改变的集合,集合不能使用add,put方法添加元素,会抛出异常
- Set接口和Map接口调用方法of时,不能有重复的元素否则会抛出异常。
import java.util.List;
import java.util.Map;
import java.util.Set;
public class OF {
public static void main(String[] args) {
List<String> list = List.of("a","b","c");
System.out.println(list);
Set<String> set =Set.of("a","d","k");
System.out.println(set);
Map<String,Integer> map =Map.of("a",1,"b",2);
System.out.println(map);
}
}
[a, b, c]
[a, d, k]
{a=1, b=2}
(二)Debug追踪
Debug调试程序:
- 可以让代码逐行执行,查看代码执行过程,调试程序中出现的bug
使用方式:
- 在行号的右边,左键单击添加断点。右键选择Debug执行程序,程序会停留在添加的第一个断点处。
执行程序:
- f8:逐行执行程序
- f7:进入到方法中
- shift+f8:跳出方法
- f9:跳到下一个断点,若没有则结束程序
- ctrl+f2:推出Debug模式,停止程序
- Console:切换到控制台