失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > map集合---------今日份下饭菜 妈妈再也不用担心我饿肚子了 学好List Set 与Map

map集合---------今日份下饭菜 妈妈再也不用担心我饿肚子了 学好List Set 与Map

时间:2021-11-30 15:35:02

相关推荐

map集合---------今日份下饭菜 妈妈再也不用担心我饿肚子了 学好List  Set 与Map

“靡不有初,鲜克有终”,读音是“mǐ bù yǒu chū,xiǎn kè yǒu zhōng”,原意是凡事都有个开始,但经常不了了之,没个结果。后借此语以讽谕持志不终的人 ,用以告诫人们为人做事要善始善终。

今天也是要好好学习的一天,你学习了吗

Map接口

在 Collection 集合中,每次操作的都是一个对象,如果现在假设要操作一对对象,比如,甲喜欢上了丙,但没有联系方法,但乙认识丙,乙和丙不是同一对象,但是通过乙可以找到丙,这就是映射关系,这种就必须使用 Map 了,类似于以下一种情况:

由于业务需求,名字和身份证号要分开存放,身份证号的唯一性和键(key)相得益彰,将身份证号存放在key中,必然可以通过唯一的键找到对应的值,不同的键可以有相同的值(可以有很多个张三(value),但身份证号(key)唯一),Map 接口里面的所有内容都按照 key -> value 的形式保存,键值对,也称为二元偶对象。

此接口定义如下:

Interface Map<K,V>

参数类型

K – 此映射维护的密钥类型

V – 映射值的类型 (K,V泛型类型,是操作者指定的类型)

Interface Map.Entry<K,​V> (Map的内部接口)键值对就是entry。 Map.entrySet方法返回 Map的集合视图,其元素属于此类

此接口与 Collection 接口没有任何的关系(并列的顶级集合接口,一个单值,一个键值对),是第二大的集合操作接口。

此接口常用方法如下:

Map接口提供了三个collection-view(collection集合视图),这些视图允许将映射的内容视为一组键集合(类型:Set ,方法: keySet()),值集合(类型:Collection , 方法:values())或键值映射集(类型:Set<Map.Entry<K,V>> , 方法 entrySet())。

Map的顺序被定义为其中在Map上的collection-view迭代返回元素的顺序。 一些Map实现,如TreeMap类,对其顺序做出了具体保证; 其他的,比如HashMap集合,没有。

注意:如果将可变对象用作映射键,则必须非常小心(最好不要将可变对象用作键值,后果很严重)。 如果在对象是Map中的键时,以影响equals比较的方式更改对象的值,则不指定映射的行为。 这种禁令的一个特例是,Map不允许将自己作为一个关键词。 虽然允许地图将自身包含为值,但建议极为谨慎: equals和hashCode方法在此类Map上不再明确定义。

Map 本身是一个接口,所以一般会使用以下的几个子类:HashMap、TreeMap、Hashtable。

HashMap集合

HashMap 是 Map 的子类,此类的定义如下:

public class HashMap<K,V> extends AbstractMap<K,V>

implements Map<K,V>, Cloneable, Serializable

(此类继承了 AbstractMap 类,同时可以被克隆,可以被序列化下来。)

基于哈希表的Map接口的实现。此实现提供了所有可选的映射操作,并允许null值和null键。( HashMap类大致相当于Hashtable ,除了它是不同步的并且允许空值。)此类不保证元素的顺序;特别是它不保证元素会随着时间的推移保持不变(当其容量不足时会重建内部数据结构,即集合会自动重新散列来扩展表)。

该实现为基本操作( get和put )提供了恒定时间性能,假设散列函数在桶之间正确地分散元素。 对集合视图的迭代需要与HashMap实例的“容量”(桶数)加上其大小(键值映射的数量)成比例的时间。 因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低)非常重要。

HashMap的实例有两个影响其性能的参数: 初始容量和负载因子。 容量是哈希表中的桶数,初始容量只是创建哈希表时的容量。 加载因子是在自动增加容量之前允许哈希表获取的完整程度的度量。 当哈希表中的桶使用数超过加载因子和当前容量的乘积时,哈希表将被重新哈希(即重建内部数据结构),以便哈希表具有大约两倍的桶数。

作为一般规则,默认加载因子(0.75)在时间和空间成本之间提供了良好的折衷。 较高的值会减少空间开销,但会增加查找成本(反映在HashMap类的大多数操作中,包括get和put )。 在设置其初始容量时,应考虑映射中的预期条目数及其负载因子,以便最小化重新散列操作的数量。 如果初始容量大于最大条目数除以加载因子,则不会发生重新加载操作。

如果要将多个映射存储在HashMap实例中,则使用足够大的容量创建映射将允许映射更有效地存储,而不是根据需要执行自动重新散列来扩展表。 请注意,使用具有许多相同hashCode()的键是减慢任何哈希表性能的可靠方法(即想要提高性能就不要有多个相同hashCode()的键)。 为了改善影响,当键为Comparable时,此类可以使用键之间的比较顺序来帮助打破关系。

构造器

方法摘要 (标红注释是我的理解)

HashMap集合底层存储数据的结构是哈希表

什么是哈希表呢?

在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。当其长度减小到6时又变回链表。(所以长度为7时是个坑,可能是链表也可能是红黑树。)

简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下图所示。

总而言之,JDK1.8引入红黑树大程度优化了HashMap的性能。

Hashtable 集合

定义:public class Hashtable<K,​V>

extends Dictionary<K,​V>

implements Map<K,​V>, Cloneable, Serializable

该类实现了一个哈希表,它将键映射到值。任何非null对象都可以用作键或值。

要成功存储和检索哈希表中的对象,用作键的对象必须实现hashCode方法和equals方法。

此示例创建数字哈希表。 它使用数字的名称作为键:

Hashtable<String, Integer> numbers = new Hashtable<String, Integer>(); numbers.put("one", 1); numbers.put("two", 2); numbers.put("three", 3);

要检索数字,请使用以下代码:

Integer n = numbers.get("two"); if (n != null) {System.out.println("two = " + n);}

从Java 2平台1.2版本开始,该类被改进以实现Map接口,使其成为Java Collections Framework的成员。 与新的集合实现不同, Hashtable是同步的。 如果不需要线程安全实现,建议使用HashMap代替Hashtable 。 如果需要线程安全的高度并发实现,则建议使用ConcurrentHashMap代替Hashtable 。

构造器

方法

两者操作方法基本一样(map各子类集合的操作方法都差不多,同理其他集合也是)

import java.util.*;import java.util.concurrent.ConcurrentHashMap;public class Demo {//HashMap/Hashtable/ConcurrentHashMap//TreeMap//LinkedHashMappublic static void main(String[] args) {//key 和 value 可以是自定义类型,key值建议不要随意更改Map<String, String> data = new TreeMap<>();data.put("key1", "赵钱孙李");//增加方法data.put("key2", "周吴郑王");data.put("key3", "1周吴郑王");data.put("key4", "小明同学");//boolean remove = data.remove("key4", "小明同");//falsedata.remove("key4");//删除方法int size = data.size();//集合内键值对数量System.out.println("集合内键值对数量:" + size);boolean empty = data.isEmpty();//集合是否为空System.out.println("集合是否为空:" + empty);data.put("", "");boolean key1 = data.containsKey("key1");//是否包含某个键,containsValue是否包含某个值System.out.println("集合是否包含key1:" + key1);//data.clear();清空集合//data.put(null, null);//只有HashMap和LinkedHashMap可以存储,其余会报空指针异常//data.put(null, null);//key不可重复,相同新value覆盖旧valueSystem.out.println(data);System.out.println("-----------以上直接输出整个集合------------");/*String value = data.get("key1");System.out.println(value);value = data.get("key2");//根据键取值System.out.println(value);*/Set<String> set = data.keySet();for (String key :set) {System.out.println(key + "->" + data.get(key));}System.out.println("------以上将key转为Set集合遍历键调用get(key)方法取值--------");Collection<String> values = data.values();//把所有值转成Collection集合for (String value :values) {System.out.println(value);}System.out.println("---------将value转为Collection集合遍历值(无法得到key)--------------");for (Map.Entry<String, String> entry : data.entrySet()) {System.out.println(entry.getKey() + "->" + entry.getValue());}System.out.println("---------将entry转为Set集合遍历键值对--------------");Iterator<Map.Entry<String, String>> iterator = data.entrySet().iterator();//Iterator<String> iterator = data.keySet().iterator();//Iterator<String> iterator = data.values().iterator();while (iterator.hasNext()) {Map.Entry<String, String> next = iterator.next();System.out.println(next);}System.out.println("-------------还能用iterator迭代器输出---------------");}}

HashMap与Hashtable的区别

在整个集合中除了 ArrayList 和 Vector 的区别之外,另外一个最重要的区别就是 HashMap 与 Hashtable 的区别。

循环方式上面代码里有示例。

map集合---------今日份下饭菜 妈妈再也不用担心我饿肚子了 学好List Set 与Map 装的下 世界就是你的

如果觉得《map集合---------今日份下饭菜 妈妈再也不用担心我饿肚子了 学好List Set 与Map》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。