首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java之映射

Java之映射

作者头像
kirin
发布于 2020-08-19 03:27:59
发布于 2020-08-19 03:27:59
1.3K00
代码可运行
举报
文章被收录于专栏:Kirin博客Kirin博客
运行总次数:0
代码可运行

集是一个集合,它可以快速地查找现有的元素。但是,要查看一个元素,需要有要查找元素的精确副本。这不是一种非常通用的查找方式,因为在集合中查找元素总是要遍历集合。通常,我们知道某些键的信息,并想要查找与之对应的元素。映射(map)数据结构就是为此而设计的。映射用来存放键/值对。如果提供了键,就能够查找到值。它们之间是一一对应关系。

1.基本映射操作

Java类库为映射提供了两个通用的实现:HashMap和TreeMap,这两个类都实现了Map接口

散列映射(HashMap)对键进行散列,树映射(TreeMap)用键的整体顺序对元素进行排序,并将其组织成搜索树。

散列或比较函数只能作用于键。与键关联的值不不能进行散列或比较

与集一样,散列映射比树映射稍微快一些,所以在不需要按照排列顺序访问键的时候,最好选用散列映射

OP->>要进行键值存储,必须使用put方法

OP->>要进行键值访问,必须使用get方法,且只能通过键来访问到值

OP->>如果找不到值却不想返回一个空对象,则使用getOrDefault(var1,var2),如果找不到值则返回var2。

键必须是唯一的,如果对一对映射调用两次put方法,则后一次调用会覆盖前一次调用。并返回第一次调用的结果

OP->>要进行键值对的移除,则要使用remove(键)的方法

OP->>要想获取键值对的数量,则要使用size()方法

OP->>要迭代处理每个键和值,最好是使用forEach方法,可以向这个方法提供一个lambda表达式,用来依次处理映射中的每一个元素

类似于scores.forEach((k,v)->System.out.println(“key=”+k+”,value=”+v));

下面示例程序演示了映射的操作过程,首先将键/值对添加到映射中。然后从映射中删除一个键,同时与之对应的值也被删除了。接下来,修改与某一个键对应的值,并调用get方法查看这个值。最后,迭代处理条目集。

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
     package Collection.Map;
 
   import java.util.*;
 
   public class MapTest {
 
   public static void main(String[] args) {
 
  Map<String,Employee> staff=new HashMap<>();
 
  staff.put(144-25-5464, new Employee(“Amy Lee”));
 
  staff.put(567-24-2546, new Employee(“Harry Hacker”));
 
  staff.put(157-62-7935, new Employee(“Gary Cooper”));  
 
  staff.put(456-62-5527, new Employee(“Francesca Cruz”));
 
  //打印所有成员
   System.out.println(staff);
  //删除某一成员
 
  staff.remove(567-24-2546);
 
  //替代一个成员
 
  staff.put(456-62-5527, new Employee(“Francesca Miller”));
 
  //查看一个成员
  System.out.println(staff.get(157-62-7935));
 
  //遍历映射
  staff.forEach((k,v)->System.out.println(“key=+k+,value=+v));
  }
   }
 
   class Employee{
 
  String name;
   public Employee(String name) {
 
   this.name = name;
  }
 
   public String toString() {
   return[name=+name+];
   }
   }

运行结果:

下面是接口Map中常用的几个方法及其解释

V get(Object key)

获取与键对应的值;返回与键对应的对象,如果在映射中没有这个对象则返回null。键可以为null。

default V getOrDefault(Object key,V defaultValue)

获得与键关联的值;返回与键关联的对象,或者如果未在映射中找到这个键,则返回defaultValue。

V put(K key,V value)

将键与对应的值关系插入到映射中。如果这个键已经存在,新的对象将取代与这个键对应的旧对象。这个方法将返回键对应的旧值。如果这个键以前没有出现过则返回null。键可以为null,但值不能为null。

void putAll(Map<? extends K,? extends V> entries)

将给定映射中所有条目添加到这个映射中。

boolean containsKey(Object key)

如果映射中已经有这个键,则返回true。

boolean containsValue(Object value)

如果映射中已经有这个值,返回true。

default void forEach(BiConsumer<? super K,? super V> action)

对这个映射中的所有键/值应用这个动作。

下面是HashMap类中的常用方法:

HashMap()

HashMap(int initialCapacity)

HashMap(int initialCapacity,float loadFactor)

用给定的容量和装填因子构造一个空散列映射(装填因子是一个0.0~1.0之间的一个数值。这个数值决定散列表填充百分比。一旦到了这个比例,就要将其再散列到更大的表中)。默认的装填因子是0.75。

下面是TreeMap类中常用的方法:

TreeMap()

为实现Comparable接口的键构造一个空的树映射

TreeMap(Comparator<? super K> c)

构造一个树映射,并使用一个指定的比较器对键进行排序

TreeMap(Map<? extends K,? extends V> entries)

构造一个树映射,并将某个映射中的所有条目添加到树映射中

TreeMap(SortedMap<? extends K,? extends V> entries)

构造一个树映射,将某个有序映射中的所有条目添加到树映射中,并使用与给定的有序映射相同的比较器。

下面是SortedMap接口的一些重要的方法

Comparator<? super K> comparator()

返回键进行排序的比较器。如果键是用Comparable接口的comparaTo方法进行比较的,返回null

K firstKey()

K lastKey()

返回映射中最小元素和最大元素

2.更新映射项

我们从前面的方法中知道,更新一个映射项使用的是put方法,但是,考虑下面一种情况,假如我想将下面一段话进行单词统计,然后将得到的结果存放到一个映射表中。

句子:I am a handsome boy and you are a beautiful girl , so we can marry , then make love , finally create new lives . I believe certainly that our son will be a handsome boy and daughter will be a beautiful girl too , because I am a handsome boy and you are a beautiful girl .

我们可以定义一个counts的映射表。如果我们想向里面添加元素,我们会想如下那样做:

counts.put(word,counts.get(word)+1);

但是有一个问题,如果原先映射表中不存在这个单词,get方法就会返回一个null,这个时候就会抛出一个NullPointerException异常。代码和结果如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package Collection.Map;
 
   import java.util.*;
 
   public class MapTest2 {
 
   public static void main(String[] args) {
 
  String words=I am a handsome boy and you are a beautiful girl , so we can marry , then make love , finally create new lives . I believe certainly “ 
  
  + “that our son will be a handsome boy and daughter will be a beautiful girl too , because I am a handsome boy and you are a beautiful girl .;
 
 
  Map<String,Integer> counts=new HashMap<>();
  Scanner in=new Scanner(words);
  String word=null;
 
   while(in.hasNext()) {
  
  word=in.next();
 
  counts.put(word, counts.get(word)+1);  }
 
   in.close();
  System.out.println(counts);
 
  }
   }

结果:

如果就使用前面我们所介绍方法,可以有以下两种解决方案,第一种是在使用put方法之前首先进行检查,第二种是使用getOrDefault方法。

下面是两种示例代码:

第一种:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   package Collection.Map; 
 
   import java.util.*;
   public class MapTest2 {
 
   public static void main(String[] args) {
  String words=I am a handsome boy and you are a beautiful girl , so we can marry , then make love , finally create new lives . I believe certainly “ 
 
 
  + “that our son will be a handsome boy and daughter will be a beautiful girl too , because I am a handsome boy and you are a beautiful girl .;
  
 
  Map<String,Integer> counts=new HashMap<>();
 
  Scanner in=new Scanner(words);
 
  String word=null; 
 
   while(in.hasNext()) {
  word=in.next();
  
   if(counts.get(word)==null) {
  counts.put(word,1);
  }else {
 
   counts.put(word, counts.get(word)+1); 
  }
  }
  in.close();
   System.out.println(counts);
  }
   }

第二种:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   package Collection.Map;

   import java.util.*;
 
   public class MapTest2 {
   public static void main(String[] args) {
  String words=I am a handsome boy and you are a beautiful girl , so we can marry , then make love , finally create new lives . I believe certainly “ 
 
  + “that our son will be a handsome boy and daughter will be a beautiful girl too , because I am a handsome boy and you are a beautiful girl .;
 
 
  Map<String,Integer> counts=new HashMap<>(); 
  
 
  Scanner in=new Scanner(words);
  String word=null;
   while(in.hasNext()) {
  word=in.next();
  
  counts.put(word, counts.getOrDefault(word, 0)+1);
 
  }
  in.close();
 
  System.out.println(counts);
  
 
  }
 }
 

结果:

除了像以上那样进行修改,下面还可以提供两种方法使其做的更好:

第一种是使用putIfAbsent方法,从字面意思上理解,就是不在的时候放入,正如我们所想,就是这样。具体在这个例子中使用的时候首先调用这个方法,如果不存在就放入一个0,然后调用put方法。第二种就是使用merge方法,merge方法是解决这个问题最好的方法,merge方法可以简化这个常见的操作,如果原先的键不存在,下面的调用:counts.merge(word,1,Integer::sum);将把word与1关联,否则使用Integer::sum方法组合原值和1(也就是将原值和1求和)。下面演示这两个解决方案:

方案1:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 
   package Collection.Map;
 
 
   import java.util.*;
   public class MapTest2 {
 
   public static void main(String[] args) {
  String words=I am a handsome boy and you are a beautiful girl , so we can marry , then make love , finally create new lives . I believe certainly “ 
 
 
  + “that our son will be a handsome boy and daughter will be a beautiful girl too , because I am a handsome boy and you are a beautiful girl .;
 
 
  Map<String,Integer> counts=new HashMap<>();
 
  Scanner in=new Scanner(words);
  String word=null;
   while(in.hasNext()) {
  word=in.next();
 
  counts.putIfAbsent(word, 0);
  counts.put(word, counts.get(word)+1);
 
  }
 
  in.close();
 
  System.out.println(counts);
  }
   }

方案二:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

   package Collection.Map;
 
   import java.util.*;
   public class MapTest2 {
 
   public static void main(String[] args) {
  String words=I am a handsome boy and you are a beautiful girl , so we can marry , then make love , finally create new lives . I believe certainly “ 
 
  + “that our son will be a handsome boy and daughter will be a beautiful girl too , because I am a handsome boy and you are a beautiful girl .;
 
  Map<String,Integer> counts=new HashMap<>();
  Scanner in=new Scanner(words);
 
  String word=null;
 
   while(in.hasNext()) {
  word=in.next();
  counts.merge(word, 1, Integer::sum);
 
  }
 
  in.close();
  System.out.println(counts);
 
  }
  }  

结果同上。

下面给出了几个常见的关于更新映射项的方法:

default V merge(K key,V value,Bifunction<? super Vzaa,? super V,? extends V> remappingFunction)

如果key与一个非null值v关联,将函数应用到v和value,将key与结果关联,或者如果结果为null,则删除这个键。否则,将key与value关联,返回get(key)

default V compute(K key,Bifunction<? super K,? super V,? extends V> remappingFunction)

将函数应用到key和get(key)。将key与结果相关联。或者如果结果为null,则删除这个键,返回get(key)

default V computeIfPresent(K key,Bifunction<? super K,? super V,? extends V> remappingFunction)

如果key与一个非null值v关联,将函数应用到key和v,将key与结果关联,或者如果为null,则删除这个键。返回get(key)

default V computeIfAbsent(K key,Function<? super K,? extends V> mappingFunction)

将函数应用到key,除非key与一个非null值关联。键key与结果关联,或者如果结果为null,则删除这个键,返回get(key)

default replaceAll(Bifunction<? super K,? super V,? extends V> remappingFunction)

在所有映射项上应用函数。将键与非null结果关联,对于null结果,则将相应的键删除。

3.映射视图

有时候我们需要查看映射中的键集合,值集合(因为值可能存在相同的元素,所以严格来说不算是一个集合),以及键/值对集合。

下面三种方式分别返回键集合,值集合,键/值对集合

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  Set<K> keySet()
 
  Collection<V> values() 
 
  Set<Map.Entry<K,V>> entrySet() 

下面一个程序演示了以上方法的调用,及其使用意义:

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
   package Collection.Map;
   import java.util.*;
 
   import java.util.Map.Entry;
   public class MapView {
 
   public static void main(String[] args) {
  Map<String,Integer> test=new HashMap<>();
 
  test.put(“于理想”,1);
 
  test.put(“张琛”,2);
 
 
  test.put(“张艳杰”,3);
 
 
  test.put(“张哲鑫”,4);
  test.put(“闫智”,5);
 
  test.put(“孙崇伟”,6);
 
  //下面枚举键:
 
  Set<String> keys=test.keySet();
 
   for(String key:keys) {
 
 
  System.out.print(key+” “);
 
  }
   System.out.println();
  //下面枚举值:
 
 
  Collection<Integer> values=test.values();
   for(Integer value:values) {
 
  System.out.print(value+” “);
   }
 
  System.out.println();
 
  //下面枚举键/值对
  Set<Map.Entry<String, Integer>> mapping=test.entrySet();
   for(Map.Entry<String, Integer> map:mapping) {
  System.out.print(map+” “);
  }
 
 
  System.out.println();
  //注意:上面最后一个曾经是访问所有映射条目的最有效的方法,但是,现在只需要使用forEach方法即可;
  test.forEach((k,v)->System.out.println(“键=+k+,=+v));
  }
  }
 

运行结果:

4.链接散列集与映射

它们是LinkedHashSet和LinkedHashMap,这两个将键/值对以插入顺序排列,其他的和HashMap基本完全一样。

参考资料《Java核心技术 卷I 第10版》

原文链接https://blog.csdn.net/qq_37080070/article/details/80573134?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.channel_param

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/08/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
映射---> 一眼看懂Map
Java类库提供两个基本的实现,HashMap和TreeMap。两个类都实现了Map接口
用户2436820
2018/09/05
7170
集合和映射(Set And Map)
  Set是一种新的数据结构,类似于数组,但是不能添加重复的元素,基于Set集合的这个特性,我们可以使用Set集合进行客户统计和词汇统计等,集合中常用的方法如下:
程序员波特
2024/01/19
2760
集合和映射(Set And Map)
JAVA--Map集合详解
特点:该集合存储键(key)值(value)对,一对一对往里存,而且要保证键(key)的唯一性。
用户7886150
2021/04/25
6650
13.2 具体的集合
Set(集):集合中的元素不按特定方式排序,并且没有重复对象。他的有些实现类能对集合中的对象按特定方式排序。 List(列表):集合中的元素按索引位置排序,可以有重复对象,允许按照对象在集合中的索引位
Mister24
2018/05/14
2.1K0
Java学习笔记之集合3
本篇主要涉及Java知识点有Map集合,Collections集合工具类和一个斗地主的案例。
Jetpropelledsnake21
2021/12/24
5840
Java学习笔记之集合3
Java基础系列(四十五):集合之Map
Map是一个接口,代表的是将键映射到值的对象。一个映射不能包含重复的键,每个键最多只能映射到一个值。
山禾说
2019/01/21
6820
Java 编程问题:五、数组、集合和数据结构
本章包括 30 个问题,涉及数组、集合和几个数据结构。其目的是为在广泛的应用中遇到的一类问题提供解决方案,包括排序、查找、比较、排序、反转、填充、合并、复制和替换。提供的解决方案是用 Java8-12 实现的,它们也可以作为解决其他相关问题的基础。在本章的最后,您将掌握广泛的知识,这些知识对于解决涉及数组、集合和数据结构的各种问题非常有用。
ApacheCN_飞龙
2022/07/11
1.7K0
第51节:Java当中的集合框架Map
Sunday(星期天)、Monday(星期一)、Tuesday(星期二)、Wednesday(星期三)、Thursday(星期四)、Friday(星期五)、Saturday(星期六)
达达前端
2019/07/03
6130
第51节:Java当中的集合框架Map
Guava集合--新集合类型
Guava引入了很多JDK没有的、但我们发现明显有用的新集合类型。这些新类型是为了和JDK集合框架共存,而没有往JDK集合抽象中硬塞其他概念。作为一般规则,Guava集合非常精准地遵循了JDK接口契约。
不会飞的小鸟
2020/07/17
1.2K0
使用Java之TreeMap,轻松实现高效有序映射!
在Java集合框架中,Map接口为我们提供了键值对的存储结构。HashMap是最常用的实现之一,因其高效的O(1)查找时间深受开发者喜爱。然而,HashMap并不能保证键值对的顺序存储。而在某些场景中,我们需要维护一个有序的键值映射,此时TreeMap便派上用场了。TreeMap基于红黑树实现,天然支持有序性。本文将深入探讨TreeMap的实现原理及其应用场景。
bug菌
2024/08/18
3180
使用Java之TreeMap,轻松实现高效有序映射!
Java集合框架(五)—— Map、HashMap、Hashtable、Properties、SortedMap、TreeMap、WeakHashMap、IdentityHashMap、EnumMap
Map Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另一组值用于保存Map里的value,key和value都可以是任何引用类型的数据。Map的key不容许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false。   key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的value。   如果把Map里的所有key放在一
10JQKA
2018/05/09
1.6K0
Java(集合④)
当方法的参数列表数据类型已经确定,但是参数个数不确定,就可以使用可变参数;
全栈开发日记
2022/05/12
8220
Java9-day04【Map】课后习题
Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在Map中是一一对应关系,这一对对象又称做Map 中的一个Entry(项)。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。
Java帮帮
2022/11/25
3150
Java9-day04【Map】课后习题
Java之HashMap详解
该类实现了Map接口,根据键的HashCode值存储数据,具有很快的访问速度,最多允许一条记录的键为null,不支持线程同步。
用户5224393
2019/08/20
1.5K0
【小Y学算法】⚡️每日LeetCode打卡⚡️——45.多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
呆呆敲代码的小Y
2021/10/08
3180
Map、斗地主案例
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/100193.html原文链接:https://javaforall.cn
全栈程序员站长
2022/06/29
1.4K0
Map、斗地主案例
Java之TreeMap详解
1. 是一个有序的key-value集合,它是通过红黑树实现的。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
用户5224393
2019/08/20
3.5K0
HashMap简介-Java快速入门教程
Java 中的 HashMap 是一个无序集合,它以键值对(称为条目)的形式存储元素(对象)。
jack.yang
2025/04/05
1720
HashMap简介-Java快速入门教程
【Java集合-2】HashMap简析
由上图可知,HashMap继承于AbstractMap类,实现了Map接口。Map是"key-value键值对"接口,AbstractMap实现了"键值对"的通用函数接口。 HashMap包括几个重要的成员变量:table, size, threshold, loadFactor, modCount。
云深i不知处
2020/09/16
3860
滚雪球学Java(65-3):详解Java IdentityHashMap的内部实现原理
咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~
bug菌
2024/08/04
1350
滚雪球学Java(65-3):详解Java IdentityHashMap的内部实现原理
相关推荐
映射---> 一眼看懂Map
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档