10_07【Java】Map集合详述

如果想要存储具有映射关系的数据,那么就需要使用Map集合了。Map集合由Map接口和Map接口的实现类组成。

一、Map接口概述

1、Map接口是什么?

Map是一个以键值对存储的接口,也就是将键映射到值的对象。映射不能包含重复的键,每个键最多可以映射到一个值,并且键不能重复,不能为空。总结来说:Map存储的是键值对,键唯一,一个键对应唯一的一个值

Map接口虽然没有继承Collection接口,但是提供了key到value的映射关系。

Interface Map<K,V>
  • K:映射的key
  • V:映射的值

Map接口提供了三个集合视图,允许将Map的内容作为单独的一组键、单独的一组值,或者是一组键值映射。映射的顺序被定义为映射集合视图上的迭代器返回元素的顺序。对一些类中元素的顺序进行了设置,比如TreeMap;而HashMap则不需要进行元素顺序保证。

2、Map接口的特点:

Map 接口中键和值一一映射,可以通过键来获取值。

  • 给定一个键和一个值,你可以将该值存储在一个 Map 对象。之后,你可以通过键来访问对应的值。
  • 当访问的值不存在的时候,方法就会抛出一个 NoSuchElementException 异常。
  • 当对象的类型和 Map 里元素类型不兼容的时候,就会抛出一个 ClassCastException 异常。
  • 当在不允许使用 Null 对象的 Map 中使用 Null 对象,会抛出一个 NullPointerException 异常。
  • 当尝试修改一个只读的 Map 时,会抛出一个 UnsupportedOperationException 异常。

3、Map的子接口及其继承关系

(1)Map接口在java.util中的位置

在这里插入图片描述

(2)Map子接口及继承关系

Map的所有子接口有:

Bindings, ConcurrentMap<K,V>, ConcurrentNavigableMap<K,V>, LogicalMessageContext, MessageContext, NavigableMap<K,V>, SOAPMessageContext, SortedMap<K,V>

其中,常用的子接口包括SortedMap和NavigebleMap,他们的继承关系如下图:
在这里插入图片描述

二、Map接口的方法

1、Map的所有方法

方法修饰符/类型描述
clear()void从该映射中删除所有映射(可选操作)
compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)defaultV尝试计算指定键及其当前映射值的映射(如果没有当前映射,则为null)。
computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)defaultV如果指定的键尚未与某个值关联(或映射为null),则尝试使用给定的映射函数计算其值并将其输入到该映射中,除非为null。
computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)defaultV如果指定键的值存在且非空,则尝试计算给定键及其当前映射值的新映射。
containsKey(Object key)boolean如果此映射包含指定键的映射,则返回true。
containsValue(Object value)boolean如果此映射将一个或多个键映射到指定的值,则返回true。
entrySet()Set<Map.Entry<K,V>>返回此映射中包含的映射的集合视图。
equals(Object o)boolean比较指定的对象与此映射是否相等。
forEach(BiConsumer<? super K,? super V> action)defaultvoid对映射中的每个条目执行给定的操作,直到所有条目都已处理或操作抛出异常为止。
get(Object key)V返回指定键映射到的值,如果该映射不包含该键的映射,则返回null。
getOrDefault(Object key, V defaultValue)defaultV返回指定键映射到的值,如果该映射不包含该键的映射,则返回defaultValue。
hashCode()int返回此映射的哈希码值。
isEmpty()boolean如果该映射不包含键-值映射,则返回true。
keySet()Set<K>返回此映射中包含的键的集合视图。
merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)defaultV如果指定的键尚未与值关联或与null关联,则将其与给定的非空值关联
put(K key, V value)V将此映射中的指定值与指定键关联(可选操作)。
putAll(Map<? extends K,? extends V> m)void将指定映射中的所有映射复制到此映射(可选操作)。
putIfAbsent(K key, V value)defaultV如果指定的键尚未与值关联(或映射为null),则将其与给定值关联并返回null,否则返回当前值。
remove(Object key)V如果密钥存在,则从该映射中删除该密钥的映射(可选操作)。
remove(Object key, Object value)defaultboolean仅当指定键项当前映射到指定值时才删除该项。
replace(K key, V value)defaultV86/5000 仅在当前映射到某个值时替换指定键的条目。
replace(K key, V oldValue, V newValue)defaultboolean仅在当前映射到指定值时替换指定键的条目。
replaceAll(BiFunction<? super K,? super V,? extends V> function)defaultvoid将每个条目的值替换为对该条目调用给定函数的结果,直到处理完所有条目或该函数抛出异常。
size()int返回此映射中键-值映射的数目。如果映射包含超过整数。MAX_VALUE元素,返回整数.MAX_VALUE。
values()Collection<V>返回此映射中包含的值的集合视图。

2、Map常用方法

实例1:Map接口常用方法应用
import java.util.*;

public class MapTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Map<String,String> map = new HashMap<>();
		map.put("01","Tom");
		map.put("02","Bob");
		map.put("05","Henry");
		map.put("04","Lily");
		map.put("07","Jack");
		map.put("010","Tony");
		Map<String,String> map2 = new TreeMap<>();
		map2.put("01","Tom");
		map2.put("02","Bob");
		map2.put("05","Henry");
		map2.put("04","Lily");
		map2.put("07","Jack");
		map2.put("010","Tony");
		System.out.println("map:"+map);
		System.out.println("map2:"+map2);
		// 返回当前数据个数
		int size = map.size();
		System.out.println("map当前键值对组数:"+size);

		// 是否为空
		boolean isEmpty = map.isEmpty();
		System.out.println("map是否为空?"+isEmpty);

		// 判断是否包含指定的key,这里用到了key的equals方法,所以key必须实现它
		boolean containsKey= map.containsKey("08");
		System.out.println("判断map是否包含指定的key:"+containsKey);

		// 判断是否有key保存的值是value,这也基于equals方法
		boolean containsValue = map.containsValue("Lily");
		System.out.println("判断map是否包含指定的value:"+containsValue);
		// 通过key获取对应的value值
		System.out.println("通过key获取map对应的value值:"+map.get("03"));
		// 存入key-value
		map.put("11", "Sam");
		map2.put("11", "Sam");
		System.out.println("现在的map:"+map);
		// 返回所有的key至Set集合中,因为key是不可重的,Set也是不可重的
		System.out.println("返回map所有的key至Set集合中:"+map.keySet());

		// 返回所有的values
		System.out.println("返回map返回所有的values至Set集合中:"+map.values());
		
		// 返回key-value对到Set中
		System.out.println("返回mapkey-value对至Set集合中:"+map.entrySet());
		
		// 希望我们实现equals和hashCode
		System.out.println("map的hashocode值:"+map.hashCode());
		System.out.println("map2的hashocode值:"+map2.hashCode());
		System.out.println("判断map和map2是否相同:"+map.equals(map2));
		// 移除一个key-value对
		
		map.remove("05");
		map2.remove("05");
		System.out.println("移除key为05的键值对后的map"+map);
		
		// 清空
		map.clear();
		System.out.println("移除所有键值对后的map"+map);
		

	}

}
ConsoleL
  
map:{01=Tom, 02=Bob, 04=Lily, 05=Henry, 07=Jack, 010=Tony}
map2:{01=Tom, 010=Tony, 02=Bob, 04=Lily, 05=Henry, 07=Jack}
map当前键值对组数:6
map是否为空?false
判断map是否包含指定的key:false
判断map是否包含指定的value:true
通过key获取map对应的value值:null
现在的map:{11=Sam, 01=Tom, 02=Bob, 04=Lily, 05=Henry, 07=Jack, 010=Tony}
返回map所有的key至Set集合中:[11, 01, 02, 04, 05, 07, 010]
返回map返回所有的values至Set集合中:[Sam, Tom, Bob, Lily, Henry, Jack, Tony]
返回mapkey-value对至Set集合中:[11=Sam, 01=Tom, 02=Bob, 04=Lily, 05=Henry, 07=Jack, 010=Tony]
map的hashocode值:77101877
map2的hashocode值:77101877
判断map和map2是否相同:true
移除key为05的键值对后的map{11=Sam, 01=Tom, 02=Bob, 04=Lily, 07=Jack, 010=Tony}
移除所有键值对后的map:{}

三、Map接口的所有实现类

1、Map接口的所有实现类

实现类描述
AbstractMap该类提供Map接口的基本实现,以最小化实现该接口所需的工作。要实现不可修改的映射,程序员只需扩展这个类并为entrySet方法提供一个实现,该方法返回映射的集合视图。通常,返回的集合将依次在AbstractSet上实现。这个集合不应该支持添加或删除方法,它的迭代器也不应该支持删除方法。要实现可修改的映射,程序员必须另外重写这个类的put方法(否则会抛出UnsupportedOperationException), entrySet().iterator()返回的迭代器必须另外实现它的remove方法。按照map接口规范中的建议,程序员通常应该提供一个void(无参数)和映射构造函数。该类中每个非抽象方法的文档都详细描述了其实现。如果正在实现的映射允许更有效的实现,则这些方法中的每一个都可能被覆盖。该类是Java Collections框架的成员
Attributes该属性类将清单属性名称映射到关联的字符串值。有效的属性名不区分大小写,只能使用集合[0-9a-zA-Z_-]中的ASCII字符,长度不能超过70个字符。属性值可以包含任何字符,并在写入输出流时采用utf8编码。有关有效属性名称和值的更多信息,请参见JAR File Specification
AuthProvider该类为提供程序定义登录和注销方法。虽然调用方可以直接调用登录,但是如果提供者确定必须在某些操作之前执行登录,它也可以代表调用方调用登录。
ConcurrentHashMap该类继承ConcurrentMap < K、V > 和NavigableMap < K、V >类。ConcurrentMap支持NavigableMap操作,并且递归地支持它的可导航子映射。该接口是Java Collection框架的成员
ConcurrentSkipListMap该类继承AbstractMap < K、V >类。实现ConcurrentNavigableMap, Cloneable, Serializable接口。ConcurrentSkipListMap是一个可扩展的并发ConcurrentNavigableMap。映射根据其键的自然顺序进行排序,或者通过在映射创建时提供的比较器进行排序,具体取决于使用的构造函数。
这个类实现了跳码器的一个并发变体,使containsKey、get、put和remove操作及其变的时间复杂度预期为log(n)。插入、删除、更新和访问操作安全地由多个线程并发执行。迭代器和分块器是弱一致的。升序键排序视图及其迭代器比降序视图更快。类中的方法返回的条目对及其视图表示生成映射时的快照。它们不支持Entry.setValue方法。(使用put、putIfAbsent或replace可以更改关联映射中的映射,具体取决于程序需要的效果)。
与大多数集合不同,由于这些映射的异步本质,size方法不是常量时间操作。确定当前元素数量需要遍历元素,因此如果在遍历期间修改了这个集合,可能会报告不准确的结果。
此外,不能保证批量操作putAll、equals、toArray、containsValue和clear会自动执行。例如,与putAll操作并发操作的迭代器可能只查看添加的部分元素。
这个类及其视图和迭代器实现了映射和迭代器接口的所有可选方法。与大多数其他并发集合一样,这个类不允许使用空键或值,因为一些空返回值无法可靠地与缺少元素区分开来。该类是Java Collections框架的成员
EnumMap继承AbstractMap < K、V >类,实现了Serializable,Cloneable接口。用于枚举类型键的专用映射实现。枚举映射中的所有键必须来自创建映射时显式或隐式指定的单个枚举类型。枚举映射在内部使用紧凑和有效的数组表示。枚举映射按照键的自然顺序(声明枚举常量的顺序)维护。这反映在集合视图返回的迭代器中(keySet()、entrySet()和values())。
集合视图返回的迭代器是弱一致性的:它们永远不会抛出ConcurrentModificationException,而且它们可能会显示在迭代过程中对映射进行的任何修改的效果。该类不允许使用空键,但允许使用空值。尝试插入空键会抛出NullPointerException。与大多数集合实现一样,EnumMap是不同步的,如果多个线程并发地访问一个枚举映射,并且至少有一个线程修改了映射,那么它应该在外部同步。这通常是通过在自然封装enum映射的对象上同步来实现的。如果不存在这样的对象,则应该使用Collections.synchronizedMap(java.util.Map< K、V >)方法。这最好在创建时完成,以防止意外的不同步访问。所有基本操作都在固定时间内执行。它们可能(尽管不能保证)比对应的HashMap更快。该类是Java Collections框架的成员
HashMap基于哈希表实现的映射接口。此实现提供了所有可选映射操作,并允许空值和空键。(HashMap类大致相当于Hashtable,只是它是不同步的,并且允许空值。)这个类不能保证映射的顺序;特别是,它不能保证顺序随时间保持不变。该类是Java Collections框架的成员
Hashtable该类实现了一个哈希表,它将键映射到值。任何非空对象都可以用作键或值。要成功地从散列表中存储和检索对象,用作键的对象必须实现hashCode方法和equals方法。该类是Java Collections框架的成员
IdentityHashMap继承AbstractMap < K、V >类,实现Map, Serializable, Cloneable接口。这个类使用散列表实现映射接口,在比较键(和值)时使用引用相等性代替对象相等性。换句话说,在一个IdentityHashMap中,当且仅当(k1==k2)时,两个键k1和k2被认为是相等的。虽然这个类实现了Map接口,但它有意违反了Map的一般约定(该约定要求在比较对象时使用equals方法),因此它不是通用的映射实现。这个类仅设计用于需要引用相等语义的极少数情况。该类是Java Collections框架的成员
LinkedHashMap该类继承HashMap类,实现了Map接口。是哈希表和链表实现的映射接口,具有可预测的迭代顺序。这个实现与HashMap的不同之处在于,它维护一个贯穿其所有条目的双链列表。这个链表定义了迭代顺序,这通常是键插入到映射中的顺序(插入顺序)。注意,如果一个键被重新插入到映射中,插入顺序不会受到影响。(如果调用m.put(k, v),那么在调用之前m. containskey (k)将返回true时,密钥k将重新插入映射m中)。该类是Java Collections框架的成员
PrinterStateReasons继承HashMap<PrinterStateReason,Severity> 类,实现 PrintServiceAttributePrinterStateReasons接口。是一个打印属性类,它是一组枚举值,提供关于打印机当前状态的附加信息,即增加打印机的PrinterState属性值的信息。
Properties继承Hashtable <Object,object>类。Properties类表示一组持久的属性。属性可以保存到流中,也可以从流中加载。属性列表中的每个键及其对应值都是一个字符串。属性列表可以包含另一个属性列表作为它的“默认值”;如果在原始属性列表中没有找到属性键,则搜索第二个属性列表。
Provider是一个public修饰的抽象类。继承Properties类,这个类表示Java安全性API的“提供程序”,其中提供程序实现Java安全性的部分或所有部分。提供者可能实现的服务包括:算法(如DSA、RSA、MD5或SHA-1);密钥生成、转换和管理功能(例如针对特定于算法的密钥)。
每个提供程序都有一个名称和版本号,并在安装它的每个运行时中进行配置。
RenderingHints继承Object类,实现了Map<Object,Object>,Cloneable接口。RenderingHints类定义并管理键和相关值的集合,这些值允许应用程序为执行呈现和图像操作服务的其他类所使用的算法的选择提供输入。Graphics2D类以及实现BufferedImageOp和RasterOp的类都提供了方法来获取或设置RenderingHints键及其关联值的单个或组。当这些实现执行任何渲染或图像处理操作时,它们应该检查调用者所请求的任何渲染函数的值,并相应地调整所使用的算法,并尽其所能。
SimpleBindings继承Object类,实现了Bindings接口。由HashMap或其他指定映射支持的简单绑定实现。
TabularDataSupport继承Object类,实现了TabularData, Map<Object,Object>, Cloneable, Serializable接口。TabularDataSupport类是开放数据类,它实现了TabularData和Map接口,并且在内部基于散列映射数据结构。
TreeMap继承AbstractMap<K,V>类,实现了NavigableMap<K,V>, Cloneable, Serializable接口。基于红黑树的NavigableMap实现。映射根据其键的自然顺序进行排序,或者通过在映射创建时提供的比较器进行排序,具体取决于使用的构造函数。这个实现为containsKey、get、put和remove操作提供了可保证的log(n)时间成本。算法是对Cormen, Leiserson和Rivest的《算法导论》中那些算法的改编。与任何排序映射一样,树映射维护的顺序,以及无论是否提供显式比较器,如果这个排序映射要正确实现map接口,则必须与equals保持一致。这是因为映射接口是根据equals操作定义的,但是排序映射使用它的compareTo(或compare)方法执行所有键比较,所以从排序映射的角度来看,这个方法认为相等的两个键是相等的。TreeMap不是线程安全的。该类是Java Collections框架的成员
UIDefaults继承Hashtable<Object,Object>类,Swing组件的默认值表。应用程序可以通过UIManager设置/获取默认值。需要注意:这个类的序列化对象将与未来的Swing版本不兼容。当前的序列化支持适用于运行相同版本Swing的应用程序之间的短期存储或RMI。从1.4开始,对所有JavaBeans™的长期存储的支持已经添加到java.bean包。
WeakHashMap继承AbstractMap<K,V>类,实现了Map<K,V>接口。基于哈希表的Map接口实现,具有弱键。当WeakHashMap中的一个条目的键不再正常使用时,它将自动被删除。更准确地说,给定键的映射的存在不会阻止该键被垃圾收集器丢弃。当一个键被丢弃时,它的条目将有效地从映射中删除,因此这个类的行为与其他映射实现略有不同。

2、Map接口常用实现类继承关系

Map接口最常用的实现类主要是TreeMap、HashMap。其继承关系如下:

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值