对 Java 中的Map集合的学习
Map集合概述
-
首先对比一下Map接口和Collection接口
复制
// Collection集合,有一个泛型<E> public interface Collection<E> extends Iterable<E> { ... } // Map集合,有两个泛型<K, V> public interface Map<K,V> { ... } -
在Collection集合中,E映射的是值的类型。在Map集合中,K映射的是键的类型,V映射的是值的类型。
-
简单的说,Map集合是一个将键(Key)映射到值(Value)的对象。且一个映射不能包含重复的键;每个键只能映射到一个值。
-
Map接口提供三种collection视图,允许以Key集、Value集、Key-Value映射关系的形式查看某个映射的内容。映射顺序定义为迭代器在映射的collection视图上返回其元素的顺序。
那什么是映射呢?在生活中,我们常常会看到这样的一种集合:账号——密码、IP地址——主机名、系统用户名——系统用户对象等。像这种一一对应的关系,就叫做映射。在Java中,Map类就是如此,专门用来存放这种对象关系的对象。
Map集合与Collection集合的区别
- collection中的集合,元素是孤立存在的(单身狗),向集合中存储元素采用一个个元素的方式存储。
- map中的集合,元素是成对存在的(情侣、夫妻),每个元素由键(key)与值(value)两个部分组成,通过键可以找到其所对应的值。
- collection中的集合成为单列集合,map中的集合称为双列集合。
- Collection接口的底层是由哈希表或哈希表+链表实现的。
- Map接口的底层是由哈希表和链接列表实现的
简单总结一下Map集合的特点
- Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)。
- Map集合中的元素,key和value的数据类型可以相同,也可以不同。
- Map集合中的元素,key是不允许重复的, value是可以重复的。
- Map集合中的元素,key和 value是一一对应的。
Map接口常用的方法
复制public V put(K key, V value) // 把指定的键与指定的值添加到Map集合中。 public V remove(Object key) // 把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值 public V get(Object key) // 根据指定的键,在Map集合中获取对应的值。 boolean containsKey(Object key) // 判断集合中是否包含指定的键。 public Set<K> keySet() // 获取Map集合中所有的键,存储到Set集合中。 public Set<Map. Entry<K,V> entrySet() // 获取到Map集合中所有的键值对对象的集合(Set集合)。
put()方法
- 作用:把指定的键与指定的值添加到Map集合中。
- 注意:
- 当要添加的key不存在的时候,调用put方法后,map集合中会添加新的
,添加成功会返回null。 - 当要添加的key存在的时候,调用put方法后,会使用新的Value替换map集合中旧的Value,替换成功会返回旧的Value。
- 当要添加的key不存在的时候,调用put方法后,map集合中会添加新的
举例
-
例子1:
复制
import java.util.HashMap; import java.util.Map; public class DemoMapPut { public static void main(String[] args) { // 用多态的形式,创建一个hashMap集合,集合长度为16 Map<String, String> hashMap = new HashMap<>(16); // 使用Map接口的特有方法put方法,向集合中添加<key-value> String return0 = hashMap.put("杨过", "小龙女"); String return1 = hashMap.put("过儿", "姑姑"); System.out.println("返回值0:" + return0); System.out.println("返回值1:" + return1); System.out.println("Map集合:" + hashMap); } } -
输出结果:
复制
返回值0:null 返回值1:null Map集合:{杨过=小龙女, 过儿=姑姑} -
例子2:
复制
import java.util.HashMap; import java.util.Map; public class Demo02MapPut { public static void main(String[] args) { Map<String, String> hashMap = new HashMap<>(16); String return0 = hashMap.put("杨过", "小龙女"); String return1 = hashMap.put("杨过", "姑姑"); System.out.println("返回值0:" + return0); System.out.println("返回值1:" + return1); System.out.println("Map集合:" + hashMap); } } -
输出结果:
复制
返回值0:null 返回值1:小龙女 Map集合:{杨过=姑姑}
remove()方法
-
作用:把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值。
-
注意:
- key存在,删除对应元素,并返回被删除的值
- key不存在,返回null
-
例子:
复制
import java.util.HashMap; import java.util.Map; public class Demo01MapRemove { public static void main(String[] args) { Map<String, String> hashMap = new HashMap<>(16); hashMap.put("key0", "value0"); hashMap.put("key1", "value1"); hashMap.put("key2", "value2"); System.out.println("没有调用remove方法前的Map集合:" + hashMap); String return0 = hashMap.remove("key0"); String return1 = hashMap.remove("key666"); System.out.println("返回值0:" + return0); System.out.println("返回值1:" + return1); System.out.println("调用remove方法后的Map集合:" + hashMap); } } -
输出结果:
复制
没有调用remove方法前的Map集合:{key1=value1, key2=value2, key0=value0} 返回值0:value0 返回值1:null 调用remove方法后的Map集合:{key1=value1, key2=value2}
get()方法
-
作用:根据指定的键,在Map集合中获取对应的值。
-
注意:
- key存在,并返回对应Value值
- key不存在,返回null
-
例子:
复制
import java.util.HashMap; import java.util.Map; public class Demo01MapGet { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("Aa", 18); hashMap.put("Bb", 20); System.out.println("key是'Aa'对应的Value是:" + hashMap.get("Aa")); System.out.println("key是'BB'对应的Value是:" +hashMap.get("BB")); } } -
输出结果:
复制
key是'Aa'对应的Value是:18 key是'BB'对应的Value是:null
containsKey()方法
-
作用:判断集合中是否包含指定的键。
-
返回值:
- key存在的情况下,返回true
- key不存在的情况下,返回false
-
例子:
复制
import java.util.HashMap; import java.util.Map; public class Demo01MapContainsKey { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("k1", 100); hashMap.put("k2", 200); System.out.println("hashMap集合:" + hashMap); boolean response1 = hashMap.containsKey("k1"); boolean response2 = hashMap.containsKey("k999"); System.out.println("是否存在键值为'k1'的元素:" + response1); System.out.println("是否存在键值为'k999'的元素:" + response2); } } -
输出结果:
复制
hashMap集合:{k1=100, k2=200} 是否存在键值为'k1'的元素:true 是否存在键值为'k999'的元素:false
keySet()方法
-
作用:获取Map集合中所有的键,存储到Set集合中。
-
返回值:返回Map集合中所有的Key的一个集合对象。
-
例子:
复制
import java.util.Map; import java.util.HashMap; import java.util.Set; public class Demo01MapKeySet { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("k1", 1); hashMap.put("k2", 2); hashMap.put("k3", 3); hashMap.put("k4", 4); hashMap.put("k5", 5); hashMap.put("k6", 6); System.out.println("hashMap:" + hashMap); // 使用keySet()方法,获取Map集合中所有的键,存储到Set集合中。 Set<String> set = hashMap.keySet(); // 输出set集合 System.out.println("set:" + set); } } -
输出结果:
复制
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6} set:[k1, k2, k3, k4, k5, k6]
entrySet()方法
-
作用:获取到Map集合中所有的键值对对象的集合(Set集合)。
-
返回值:返回值是一个key-value的Set集合对象
-
注意:由于Map集合中有两个泛型(K, V),Set集合中只有一个泛型,所以不能直接赋值给Set对象,但可以通过Map.Entry的方式赋值给Set对象
-
如:
抛出错误:
-
或者又如:
抛出错误:
-
赋值给Set集合对象:
-
entrySet方法举例:
复制
import java.util.HashMap; import java.util.Map; public class Demo01MapEntrySet { public static void main(String[] args) { Map<String, String> hashMap = new HashMap<>(16); hashMap.put("k1", "1"); hashMap.put("k2", "2"); hashMap.put("k3", "3"); hashMap.put("k4", "4"); hashMap.put("k5", "5"); hashMap.put("k6", "6"); System.out.println("hashMap:" + hashMap); // 调用entrySet方法,获取到Map集合中所有的键值对对象的集合 System.out.println("键值对对象的集合:" + hashMap.entrySet()); } } -
输出结果:
复制
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6} 键值对对象的集合:[k1=1, k2=2, k3=3, k4=4, k5=5, k6=6]
Map集合遍历键(key)的方式找值(Value)
-
通过Map集合的keySet()方法,获取Map集合中所有的Key,存储到Set集合中
-
遍历Set集合,获取每个Key所对应的Value
-
举例:
复制
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Demo01MapIteratorKey { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("k1", 1); hashMap.put("k2", 2); hashMap.put("k3", 3); hashMap.put("k4", 4); hashMap.put("k5", 5); hashMap.put("k6", 6); System.out.println("hashMap:" + hashMap); Set<String> sKey = hashMap.keySet(); // 获取Set集合的迭代器对象,并遍历该迭代器对象 Iterator<String> ite = sKey.iterator(); while (ite.hasNext()) { // 通过迭代器对象中的每一个值(Map集合中的键),获取key-value System.out.println( "Key:" + ite.next() + " Value:" + hashMap.get(ite.next()) ); } } } -
输出结果:
复制
hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6} Key:k1 Value:2 Key:k3 Value:4 Key:k5 Value:6
Map集合遍历键值对方式
例子理解:
复制import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Demo01MapIteratorKeyValue { public static void main(String[] args) { Map<String, Integer> hashMap = new HashMap<>(16); hashMap.put("k1", 1); hashMap.put("k2", 2); hashMap.put("k3", 3); hashMap.put("k4", 4); hashMap.put("k5", 5); hashMap.put("k6", 6); System.out.println("hashMap:" + hashMap); Set<Map.Entry<String, Integer>> keyValue = hashMap.entrySet(); // 获取Set集合的迭代器对象,并遍历该迭代器对象 Iterator<Map.Entry<String, Integer>> ite = keyValue.iterator(); while (ite.hasNext()) { // 通过Entry对象的getKey()和getValue()方法,获取Key和Value Map.Entry<String, Integer> kv = ite.next(); System.out.println( "Key:" + kv.getKey() + " Value:" + kv.getValue() ); } } }
输出结果:
复制hashMap:{k1=1, k2=2, k3=3, k4=4, k5=5, k6=6} Key:k1 Value:1 Key:k2 Value:2 Key:k3 Value:3 Key:k4 Value:4 Key:k5 Value:5 Key:k6 Value:6
HashMap存储自定义类型的键值
注意:Map集合,要保证Key是唯一的。作为Key的元素,必须重写hashCode()方法和equals()方法,才能保证Key的唯一性
代码理解
-
创建一个Student类,用左Map中Key的数据类型:
复制
public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } } -
创建两个方法:
- 方法1使用<String, String>为<key, value>的数据类型
- 方法2使用<Student, String>为<key, value>的数据类型
复制
import java.util.HashMap; import java.util.Map; public class MapRepeat { /** * String类型已经重写了hashCode()方法和equals()方法 * 可以保证key唯一 */ public static void method01() { Map<String, String> map = new HashMap<>(16); map.put("k1", "v1"); map.put("k2", "v2"); map.put("k3", "v3"); map.put("k4", "v4"); map.put("k1", "v5"); System.out.println(map); } /** * Student类型没有重写hashCode()方法和equals()方法 * 不能保证key唯一 */ public static void method02() { Map<Student, String> map = new HashMap<>(16); map.put(new Student("学生1", 22), "v1"); map.put(new Student("学生2", 18), "v2"); map.put(new Student("学生3", 19), "v3"); map.put(new Student("学生4", 21), "v4"); map.put(new Student("学生1", 22), "v5"); System.out.println(map); } } -
比较这两个方法:
复制
public class Demo01MapRepeat { public static void main(String[] args) { // Map<String, String>,String类已经重写了hashCode()方法和equals()方法 MapRepeat.method01(); // Map<Student, String>,Student类没有重写了hashCode()方法和equals()方法 MapRepeat.method02(); } } -
输出结果:
复制
{k1=v5, k2=v2, k3=v3, k4=v4} {Student{name='学生1', age=22}=v1, Student{name='学生1', age=22}=v5, Student{name='学生2', age=18}=v2, Student{name='学生4', age=21}=v4, Student{name='学生3', age=19}=v3}
可以看到,方法1输出的集合,并没有重复的Key,而方法2输出的集合存在冲的的Key。其中重复的Key是Student{name='学生1', age=22}
在Student类中重写hashCode()方法和equals()方法
复制import java.util.Objects; public class Student { @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
那么对MapRepeat.method02()测试,输出结果则是:
复制{Student{name='学生4', age=21}=v4, Student{name='学生2', age=18}=v2, Student{name='学生3', age=19}=v3, Student{name='学生1', age=22}=v5}
可以看出,与没有重写hashCode()方法和equals()方法前相比,重写后,不存在重复的key了。
LinkedHashMap集合简单了解
-
说明:
- LinkedHashMap类是HashMap的子类
- LinkedHashMap底层采用的是哈希表+链表结构,LinkedHashMap集合是有存取顺序的集合,而其父类HashMap是没有存取顺序的集合
-
例子:
复制
import java.util.Map; import java.util.HashMap; import java.util.LinkedHashMap; public class DemoLinkedHashMap { public static void main(String[] args) { // 无序Map集合:HashMap Map<Integer, Integer> hashMap = new HashMap<>(16); hashMap.put(1, 200); hashMap.put(3, 400); hashMap.put(5, 600); hashMap.put(2, 100); hashMap.put(4, 300); hashMap.put(6, 500); System.out.println(hashMap); // 有序Map集合:LinkedHashMap Map<Integer, Integer> linked = new LinkedHashMap<>(16); linked.put(1, 200); linked.put(3, 400); linked.put(5, 600); linked.put(2, 100); linked.put(4, 300); linked.put(6, 500); System.out.println(linked); } } -
输出结果:
复制
{1=200, 2=100, 3=400, 4=300, 5=600, 6=500} {1=200, 3=400, 5=600, 2=100, 4=300, 6=500}
Hashtable集合的简单了解
说明
- java.utiL.Hashtable<k, v>集合 implements Map<K,V>接口Hashtable
- 底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
- HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
- ArrayList集合、LinkedList集合、HashSet集合、HashMap集合等:可以存储null值【null键】
- Hashtable集合,不能存储null值,null键
- Hashtable和Vector集合一样,在jdk1.2版本之后被更先进的集合( HashMap、 ArrayList)取代了
- Hashtable的子类 Properties依然活跃在历史舞台
- Properties集合是一个唯一和I0流相结合的集合
Hashtable传入null,抛出错误
例子
复制import java.util.HashMap; import java.util.Hashtable; public class DemoHashTable { public static void main(String[] args) { HashMap<String, String> hashMap = new HashMap<>(16); hashMap.put(null, null); hashMap.put(null, "A"); hashMap.put("A", null); hashMap.put("B", "B"); System.out.println("hashMap:" + hashMap); Hashtable<String, String> hashtable = new Hashtable<>(16); // Hashtable集合,key和value都不能是null // 如果传入空值,会抛出错误:空指针异常(NullPointerException) // hashtable.put(null, null); // hashtable.put(null, "A"); // hashtable.put("A", null); hashtable.put("B", "B"); System.out.println("hashtable:" + hashtable); } }
输出结果:
复制hashMap:{null=A, A=null, B=B} hashtable:{B=B}
本文来自博客园,作者:LeeHua,转载请注明原文链接:https://www.cnblogs.com/liyihua/p/12199448.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)