Java与Go:Map

Map(也可以成为字典,映射表)是一种数据结构,用于存储键值对(key-value pairs)。它是一种抽象的数据类型并且允许通过键来快速查找和访问与之相关联的值。在Java和Go中,Map提供了一种非常方便的方式来管理和组织数据。只是在Java中Map仅是一个接口,今天我们来介绍HashMap。

Java的HashMap

Java的HashMap是Java集合框架中的一种实现,用于存储键值对(key-value pairs)。它提供了快速的插入、删除和查找操作,是基于哈希表实现的。

特点:

键唯一性:HashMap中的键是唯一的,每个键只能对应一个值。如果插入已经存在的键,则会替换原有的值。
无序性:HashMap中的键值对是无序存储的,不保证存储和遍历的顺序。
允许null键和null值:HashMap中允许存储null键和null值,但只能有一个null键。

基本操作:

  • put(key, value):将指定的键值对存储到HashMap中。如果键已经存在,则更新对应的值。
  • get(key):根据键获取对应的值。
  • remove(key):根据键删除对应的键值对。
  • containsKey(key):判断HashMap中是否包含指定的键。
  • containsValue(value):判断HashMap中是否包含指定的值。
  • size():返回HashMap中键值对的数量。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;public class Main {public static void main(String[] args) {// 创建一个HashMapHashMap<String, Integer> map = new HashMap<>();// 添加键值对map.put("apple", 1);map.put("banana", 2);map.put("orange", 3);// 获取值int value = map.get("apple");System.out.println("Value of apple: " + value);// 删除键值对map.remove("orange");System.out.println("Map after removing orange: " + map);// 判断是否包含键boolean containsKey = map.containsKey("banana");System.out.println("Contains key banana: " + containsKey);// 判断是否包含值boolean containsValue = map.containsValue(2);System.out.println("Contains value 2: " + containsValue);// 获取大小int size = map.size();System.out.println("Size of map: " + size);
}

内部实现:

HashMap基于数组和链表(或红黑树)实现。当插入元素时,首先根据键的哈希值计算存储位置(索引),然后将键值对存储在数组的相应位置。如果多个键的哈希值相同,它们会存储在同一个位置,并通过链表(或红黑树)连接起来。

遍历HashMap:
HashMap可以通过迭代器或者forEach循环进行遍历。但是需要注意,由于HashMap是无序的,遍历时得到的元素顺序并不是插入顺序。

HashMap<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);// 使用迭代器遍历
Iterator<Map.Entry<String, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {Map.Entry<String, Integer> entry = iterator.next();System.out.println(entry.getKey() + " : " + entry.getValue());
}// 使用forEach循环遍历
map.forEach((key, value) -> System.out.println(key + " : " + value));

注意事项:

  • 线程不安全:
    HashMap不是线程安全的,如果多个线程同时修改HashMap,可能会导致数据不一致或者并发修改异常。
  • 扩容:
    当HashMap中的键值对数量超过负载因子(load factor)和初始容量的乘积时,HashMap会自动进行扩容,重新分配存储空间,这可能会导致性能下降。

要注意在并发环境中,可以使用Collections.synchronizedMap(Map<K,V> m)方法创建线程安全的HashMap。另外,Java 8引入了ConcurrentHashMap,它是一种并发安全的HashMap实现,适用于高并发环境。

其他的小技巧

这里介绍两个方法,我之前刷LC经常用,写来比较简洁

1.computeIfPresent

computeIfPresent() 是 Java 8 引入的HashMap方法之一,它允许我们根据指定的键和函数对HashMap中已存在的键(key)的值进行修改或计算。如果指定的键不存在,则不执行任何操作。该方法的签名如下:

V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)
  • key:要修改值的键。
  • remappingFunction:一个函数接口,用于根据给定的键和值计算新值的函数。
    该方法的工作原理是:

如果给定的键在HashMap中存在,并且对应的值不为null,则会将该键与对应的值作为参数传递给 remappingFunction 函数,然后将函数的返回值作为新的值放回HashMap中。
如果给定的键不存在或者对应的值为null,则不执行任何操作。
下面是一个简单的示例,演示了如何使用 computeIfPresent() 方法:

import java.util.HashMap;
import java.util.Map;public class Main {public static void main(String[] args) {// 创建一个HashMap并添加一些键值对Map<String, Integer> map = new HashMap<>();map.put("apple", 1);map.put("banana", 2);// 修改已存在的键值对map.computeIfPresent("apple", (key, value) -> value + 1);System.out.println("After computeIfPresent: " + map); // 输出: After computeIfPresent: {apple=2, banana=2}// 尝试修改不存在的键值对map.computeIfPresent("orange", (key, value) -> value + 1);System.out.println("After computeIfPresent: " + map); // 输出: After computeIfPresent: {apple=2, banana=2}}
}

在这个示例中,我们首先创建了一个包含一些键值对的HashMap。然后使用 computeIfPresent() 方法修改了键 “apple” 对应的值。由于 “apple” 键存在,所以对应的值会被加1。接着,我们尝试修改一个不存在的键 “orange”,但由于该键不存在,所以不会有任何操作发生。

1.computeIfAbsent

同上,不同的是仅当指定的键在HashMap中不存在或其对应的值为null时。如果指定的键已经存在且对应的值不为null,则不执行任何操作。该方法的签名如下:

V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
  • key:要检查并计算值的键。
  • mappingFunction:一个函数接口,用于根据给定的键计算新值的函数。
    该方法的工作原理是:

如果给定的键在HashMap中不存在或者对应的值为null,则会将该键与 mappingFunction 计算得到的新值放入HashMap中。
如果给定的键在HashMap中已经存在且对应的值不为null,则不执行任何操作。
下面是一个示例,演示了如何使用 computeIfAbsent() 方法:

import java.util.HashMap;
import java.util.Map;public class Main {public static void main(String[] args) {// 创建一个HashMap并添加一些键值对Map<String, Integer> map = new HashMap<>();map.put("apple", 1);map.put("banana", null); // 添加一个值为null的键值对// 使用computeIfAbsent计算值并放入HashMapmap.computeIfAbsent("apple", key -> 5); // apple键已存在,不会执行map.computeIfAbsent("orange", key -> 3); // orange键不存在,会执行System.out.println(map); // 输出: {apple=1, banana=null, orange=3}}
}

在这个示例中,我们首先创建了一个包含一些键值对的HashMap。然后使用 computeIfAbsent() 方法计算了键 “apple” 和 “orange” 对应的值。由于 “apple” 键已经存在,所以对应的值不会被修改。而 “orange” 键不存在,所以会根据给定的函数计算新值,并放入HashMap中。

Go的Map

在Go语言中,Map是一种内置的数据结构,用于存储键值对。它是一种无序的集合,类似于其他编程语言中的字典(dictionary)或哈希表(hash table)。下面是关于Go语言中Map的详细介绍:

特点:

  • 键和值类型:在Go语言中,Map的值可以是任意类型,但是所有值的类型也必须相同。但是Map的键(key)必须是支持相等操作符(==)的类型。具体来说,可以用作Map键的类型必须满足以下要求:
  • 不能是函数类型、映射类型或切片类型。
  • 不能是包含任何不可比较类型的结构体类型。
  • 不能是任何不可比较类型的接口类型。

换句话说,Go语言的Map键必须是可比较的类型,以便在内部进行散列计算和比较操作。常见的可比较类型包括整数、浮点数、字符串、指针等

  • 无序性:Map是无序的,不保证存储和遍历的顺序。
  • 动态增长:Map可以动态地增长,可以根据需要插入或删除键值对。

声明和初始化:

在Go语言中,声明和初始化Map的语法如下:

// 声明一个空的Map
var m map[keyType]valueType// 初始化Map并添加元素
m := make(map[keyType]valueType)// 直接初始化并添加元素
m := map[keyType]valueType{key1: value1,key2: value2,// more key-value pairs
}

基本操作:

  • 添加和修改键值对:
m[key] = value
  • 获取值:
value := m[key]
  • 删除键值对:
delete(m, key)
  • 检查键是否存在:
value, ok := m[key]
if ok {// key存在
} else {// key不存在
}

这里多嘴一句来解释上述格式:

“ok-idiom” 模式是 Go 语言中一种常见的惯用语法,用于处理函数返回的多个值中的第二个值,通常用来判断操作是否成功或者目标是否存在。在这种模式中,通常会使用一个布尔值来表示操作是否成功或者目标是否存在。第一个变量用于接收函数返回的值,第二个变量用于接收一个布尔值,表示操作是否成功。在 Go 语言中,通常将这个布尔值命名为 “ok”。

  • 获取Map的长度:
length := len(m)

示例:
下面是一个简单的示例,展示了如何声明、初始化、添加、获取、删除Map中的键值对:

package mainimport "fmt"func main() {// 声明和初始化Mapm := make(map[string]int)// 添加键值对m["apple"] = 1m["banana"] = 2m["orange"] = 3// 获取值fmt.Println("Value of apple:", m["apple"])// 删除键值对delete(m, "orange")// 检查键是否存在value, ok := m["banana"]if ok {fmt.Println("Value of banana:", value)}// 获取Map的长度fmt.Println("Length of map:", len(m))// 遍历Mapfor key, value := range m {fmt.Println(key, ":", value)}
}

总结

本文简单介绍Java和Go用于存储键值对的数据结构-Map,但Java的Map是一个接口,有多种实现类,而Go的Map是一种内置的数据类型,用于在内存中快速存储和检索键值对;它们都具有动态增长和无序性。不过使用时注意是否线程安全。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/749130.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文章管理AI在架构设计中的关键作用

随着信息技术的飞速发展&#xff0c;人工智能&#xff08;AI&#xff09;已逐渐成为各行业的创新引擎。在内容管理领域&#xff0c;文章管理AI的崛起不仅改变了传统的内容生产方式&#xff0c;更在架构设计层面展现出其独特的价值和潜力。本文旨在深入探讨文章管理AI在架构设计…

AJAX学习日记——Day 2

一、Bootstrap 1、功能&#xff1a;不离开当前页面&#xff0c;显示单独内容 2、导入&#xff1a; 1、导入bootstrap.css<link href"https://cdn.jsdelivr.net/npm/bootstrap5.3.0-alpha1/dist/css/bootstrap.min.css" rel"stylesheet" integrity&qu…

手机网络连接性能API接口:查询手机网络连接性能状态

手机在网状态查询服务是一项非常方便的服务&#xff0c;可以帮助我们随时了解一个手机号码的在网状态。不论是查询自己的手机号码&#xff0c;还是查询他人的手机号码&#xff0c;这个服务都可以帮助我们获取准确的信息。今天&#xff0c;我想和大家介绍一个非常好用的手机在网…

力扣100题—持续更新

目录 LC141环形列表(easy)题目描述方法1&#xff1a;快慢指针&#xff08;1&#xff09;思路&#xff08;2&#xff09;python代码&#xff08;3&#xff09;复杂度分析 LC881救生艇&#xff08;medium&#xff09;题目描述方法1&#xff1a;双指针-对撞指针&#xff08;1&…

C++三级2021考题

我家的门牌号 #include<bits/stdc.h> using namespace std; int n,m,sum0; int a[100]; void f(int); int x(int); int main() {int s;cin>>n;for(int i1;true;i){s(1i)*i/2;for(int j1;j<i;j){if(s-2*jn){cout<<j<<i;return 0;}}}return 0; } voi…

柚见第十二期(随机匹配)

随机匹配 目的 为了帮大家更快地发现和自己兴趣相同的朋友 问题 匹配 1 个还是匹配多个&#xff1f; 答&#xff1a;匹配多个&#xff0c;并且按照匹配的相似度从高到低排序 怎么匹配&#xff1f;&#xff08;根据什么匹配&#xff09; 答&#xff1a;标签 tags 还可以根据 us…

分享一下自己总结的7万多字java面试笔记和一些面试视频,简历啥的,已大厂上岸

分享一下自己总结的7万多字java面试笔记和一些面试视频&#xff0c;简历啥的&#xff0c;已大厂上岸 自己总结的面试简历资料&#xff1a;https://pan.quark.cn/s/8b602fe53b58 文章目录 SSMspringspring 的优点&#xff1f;IoC和AOP的理解**Bean 的生命周期****列举一些重要…

20个最佳ChatGPT创业提示

20 Best ChatGPT Prompts for Start-Ups 在初创企业不断变化的生态系统中&#xff0c;利用像 ChatGPT 这样的尖端工具可以成为改变游戏规则的因素。初创企业以其敏捷性和创新性而闻名&#xff0c;总是在寻找提高效率、创造力和竞争力的方法。ChatGPT 凭借其先进的功能&#xf…

leetcode2684--矩阵中移动的最大次数

1. 题意 矩阵中一个位置只能从左上一、左、左下一格子转移而来&#xff0c;且当前值一定大于转移之前的值&#xff1b; 求从第一列开始的最大转移步数。 矩阵中移动的最大次数 2. 题解 思路 由于状态只能从左向右转移&#xff0c;所以同一个位置被搜索到后&#xff0c;第一…

一命通关差分

本章节是前缀和的延申 一命通关前缀和-CSDN博客https://blog.csdn.net/qq_74260823/article/details/136530291?spm1001.2014.3001.5501 一命通关前缀和 公交车 引入 还是利用我们在前缀和中所采用的例子——公交车。 有一辆公交车&#xff0c;一共上下了N批乘客&#xff1a…

【Vue3】源码解析-Runtime

文章目录 系列文章packages/runtime-dom/src/index.ts初始化创建renderermount \src\runtime-core\component.jsh.tspackages/runtime-core/src/renderer.ts挂载及卸载DOM节点render packages/runtime-dom/src/nodeOps.tspackages/runtime-core/src/apiCreateApp.ts创建appmoun…

前端UNIAPP端webview嵌入H5使用说明文档

一、关闭webView窗口 plus.webview.close( id_wvobj, aniClose, duration, extras ); 功能说明 关闭已经打开的Webview窗口&#xff0c;需先获取窗口对象或窗口id&#xff0c;并可指定关闭窗口的动画及动画持续时间。 参数说明 参数是否必须参数类型/固定值说明id_wvobj是…

GPT-3后的下一步:大型语言模型的未来方向

摘要&#xff1a; 本文将概述GPT-3后的下一步&#xff1a;大型语言模型的未来方向&#xff0c;包括技术发展趋势、应用场景、挑战与机遇。 引言&#xff1a; GPT-3是OpenAI于2020年发布的一款大型语言模型&#xff0c;它在自然语言处理领域取得了突破性进展。GPT-3的出现标志…

全国农产品价格分析预测可视化系统设计与实现

全国农产品价格分析预测可视化系统设计与实现 【摘要】在当今信息化社会&#xff0c;数据的可视化已成为决策和分析的重要工具。尤其是在农业领域&#xff0c;了解和预测农产品价格趋势对于农民、政府和相关企业都至关重要。为了满足这一需求&#xff0c;设计并实现了全国农产…

RabbitMQ 面试题及答案整理,最新面试题

RabbitMQ的核心组件有哪些&#xff1f; RabbitMQ的核心组件包括&#xff1a; 1、生产者&#xff08;Producer&#xff09;&#xff1a; 生产者是发送消息到RabbitMQ的应用程序。 2、消费者&#xff08;Consumer&#xff09;&#xff1a; 消费者是接收RabbitMQ消息的应用程序…

哥斯拉流量webshell分析-->ASP/PHP

哥斯拉流量webshell分析 哥斯拉是继菜刀、蚁剑、冰蝎之后的又一个webshell利器&#xff0c;这里就不过多介绍了。 哥斯拉GitHub地址&#xff1a;https://github.com/BeichenDream/Godzilla 很多一线师傅不太了解其中的加解密手法&#xff0c;无法进行解密&#xff0c;这篇文章…

Vue.js基础

表单输入绑定 基础用法 v-model 指令在表单 <input>、<textarea>及 <select> 元素上创建双向数据绑定。 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据&#xff0c;并对一些极端场景进行一些特殊处理。 vue 模板语法包括两大类 插值语法…

Java算法之数论基础

Java算法之数论基础 一、最大公约数&#xff08;Greatest Common Divisor, GCD&#xff09; 在Java中&#xff0c;我们可以使用欧几里得算法&#xff08;辗转相除法&#xff09;来求两个数的最大公约数&#xff1a; 辗转相除法&#xff08;欧几里得算法&#xff09; 辗转相…

会议室预约系统优化(蓝桥杯)

文章目录 会议室预约系统优化问题描述差分 会议室预约系统优化 问题描述 假设你是一家大型企业的 IT 工程师&#xff0c;企业内有 n 个会议室&#xff0c;每天都有多个部门预约会议室进行会议。你的任务是优化现有的会议室预约系统。 你需要设计一个程序来支持以下两种操作…

Web3社交项目UXLINK零撸教程

简介&#xff1a;UXLINK是Web3行业中首个主打双向、熟人社交关系的产品&#xff0c;与其他社交基础设施类项目相比&#xff0c;类似Twitter Vs Facebook、微博 Vs 微信的社交结构区别。UXLINK的愿景&#xff1a;1、社交中心&#xff1a;成为最大的社交平台&#xff0c;专注于真…