JAVA--Map集合详解

2023-11-14

       特点:该集合存储键(key)值(value)对,一对一对往里存,而且要保证键(key)的唯一性。

       Map集合和Set集合很像,其实Set集合底层就是使用了Map集合。

什么时候使用Map集合:

    数据之间存在映射关系时,优先考虑Map集合。

Map集合常用共有方法

1.添加

V put(K key, V value):将指定的值与此映射中的指定键关联,添加键值对。

void putAll(Map<? extends K,? extends V> m):从指定映射中将所有映射关系复制到此映射中,批量添加键值对。

2.删除

void clear():从此映射中移除所有映射关系,清空所有键值对。

V remove(Object key):如果存在一个键的映射关系,则将其从此映射中移除,删除单个键值对。

3.判断

boolean containsKey(Object key):如果此映射包含指定键的映射关系(是否包含该键),则返回 true。

boolean containsValue(Object value):如果此映射将一个或多个键映射到指定值(是否包含该值),则返回 true。

boolean isEmpty():如果此映射未包含键-值映射关系,该map集合为空,则返回 true。

4.获取

V get(Object key):返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

int size():返回此映射中的键-值映射关系(键值对)数。

Collection<V> values():返回此映射中包含的值的 Collection 视图(集合)。

重点取出方式:

Set<K> keySet():返回此映射中包含的键的 Set 视图(集合)。

Set<Map.Entry<K,V>> entrySet():返回此映射中包含的映射关系的 Set 视图(集合)。

练习

class MapDemo{
	public static void main(String[] args){
		Map<String,String> map=new HashMap<String,String>();
		
		// 添加元素,如果出现相同的键,那么后添加的值会覆盖原有键对应值。
		// put方法会返回被覆盖的值。
		System.out.println("put:"+map.put("01","zhangsan1"));
		System.out.println("put:"+map.put("01","wangwu"));
		map.put("02","zhangsan2");
		map.put("03","zhangsan3");
		
		System.out.println("containsKey:"+map.containsKey("022"));
		System.out.println("remove:"+map.remove("02"));
		
		System.out.println("get:"+map.get("023"));
		
		map.put("04",null);	// 一般值不要存储null,没有意义
		System.out.println("get:"+map.get("04"));
		// 可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断
		
		// 获取map集合中所有的值
		Collection<String> coll=map.values();
		
		System.out.println(coll);
		System.out.println(map);
		
	}
}

Hashtable

底层是哈希表数据结构

特点:不可以存入null键null值,该集合是线程同步的,JDK1.0出现,效率低。

HashMap

底层是哈希表数据结构

特点:允许使用null值和null键,该集合是线程不同步的,JDK1.2出现,效率高。

Map集合的两种取出方式

Map集合的取出原理:将Map集合转成Set集合,再通过迭代器取出。

  1. Set<K> keySet():

将Map集合中所有的键存入到Set集合。因为Set集合具备迭代器,所以可以通过迭代方法取出所有的键,再根据get()方法,获取每一个键对应的值。

      2.Set<Map.Entry<K,V>> entrySet():

将Map集合中的映射关系存入到了Set集合中,而这个映射关系的数据类型就是:Map.Entry。

   Map.Entry:其实Entry也是一个接口,它是Map接口中的一个内部接口。 

interface Map{
	public static interface Entry{
		public abstract Object getKey();
		public abstract Object getValue();
	}
}

class HashMap implements Map{
	class Hahs implements Map.Entry{
		public Object getKey(){};
		public Object getValue(){};
	}
}

案例 

import java.util.*;
class MapDemo2{
	public static void main(String[] args){
	Map<String,String> map=new HashMap<String,String>();
	
	map.put("02","zhangsan2");
	map.put("03","zhangsan3");
	map.put("01","zhangsan1");
	map.put("04","zhangsan4");
	
	/*// 方法一:通过keySet()获取Map集合元素
	// 先获取Map集合的所有键的Set集合,通过keySet()方法获取到
	Set<String> keySet=map.keySet();
	
	// 有了键的Set集合,就可以获取其迭代器
	Iterator<String> it=keySet.iterator();
	while(it.hasNext()){
		String key=it.next();
		// 有了键可以通过Map集合的get()方法获取其对应的值
		String value=map.get(key);
		System.out.println("Key:"+key+",value:"+value);
	}*/
	
	// 方法二:通过entrySet()获取Map集合元素
	// 先获取Map集合中的映射关系的Set集合,通过entrySet()方法获取到
	Set<Map.Entry<String,String>> entrySet=map.entrySet();
	
	// 有了键的Set集合,就可以获取其迭代器
	Iterator<Map.Entry<String,String>> it=entrySet.iterator();
	while(it.hasNext()){
		Map.Entry<String,String> me=it.next();
		// 有了映射关系可以通过映射关系的getKey()和getValue()方法获取其对应的键值
		String key=me.getKey();
		String value=me.getValue();
		System.out.println("Key:"+key+",value:"+value);
	}
	
	}
}

练习

import java.util.*;
/*
目标:
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。
保证学生的唯一性。

思路:
1.描述学生;
2.定义Map容器。将学生(唯一性)作为键,地址作为值,存入;
3.获取Map集合中的元素。
*/
class MapTest{
	public static void main(String[] args){
	Map<Student,String> map=new HashMap<Student,String>();
	
	map.put(new Student("lisi1",21),"beijing");
	map.put(new Student("lisi1",21),"tainjin");
	map.put(new Student("lisi2",22),"shanghai");
	map.put(new Student("lisi3",23),"nanjing");
	map.put(new Student("lisi4",24),"jinan");
	
	// 第一种取出方式keySet
	Set<Student> keySet=map.keySet();
	
	Iterator<Student> it=keySet.iterator();
	while(it.hasNext()){
		Student stu=it.next();
		String addr=map.get(stu);	
		sop(stu+"..."+addr);
	}
	
	// 第二种取出方式entrySet
	Set<Map.Entry<Student,String>> entrySet=map.entrySet();
	
	Iterator<Map.Entry<Student,String>> it2=entrySet.iterator();
	while(it2.hasNext()){
		Map.Entry<Student,String> me=it2.next();
		Student stu=me.getKey();
		String addr=me.getValue();
		sop(stu+"......"+addr);
	}
	
	}
	
	// 打印语句
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

// 学生类,保证学生的唯一性
class Student implements Comparable<Student>{	
	private String name;
	private int age;
	
	public Student(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	// 防止该对象往二叉树数据类型集合中存储报异常,应使该对象具备可比性
	public int compareTo(Student s){
		int num=new Integer(this.age).compareTo(new Integer(s.age));
		
		if(num==0)
			return this.name.compareTo(s.name);
		
		return num;
	}
	
	// 保证学生的唯一性
	public int hashCode(){
		return this.name.hashCode()+age*35;
	}
	
	public boolean equals(Object obj){
		
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配!");
		
		Student s=(Student)obj;
		
		return this.name.equals(s.name) && this.age==s.age;
	}
	
	public String getName(){
		return name;
	}
	
	public int getAge(){
		return age;
	}
	
	public String toString(){
		return name+":"+age;
	}
}

TreeMap

底层是二叉树(红黑树)数据结构

特点:线程不同步,可以同时给Map集合中的键进行排序。

案例

import java.util.*;
/*
目标:
每一个学生都有对应的归属地。
学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。
保证学生的唯一性。
并且对学生对象大的年龄进行升序排序。

思路:
因为数据是以键值对形式存在的,
所以要使用可以排序的Map集合:TreeMap。
1.描述学生;
2.定义Map容器。将学生(唯一性)作为键,地址作为值,存入;
3.获取Map集合中的元素。
*/
class MapTest2{
	public static void main(String[] args){
	TreeMap<Student,String> tm=new TreeMap<Student,String>(new StuNameComparator());	 
	
	tm.put(new Student("lisi1",21),"beijing");
	tm.put(new Student("blisi3",23),"nanjing");
	// tm.put(new Student("lisi1",21),"tainjin");
	tm.put(new Student("alisi4",24),"jinan");
	tm.put(new Student("lisi2",22),"shanghai");
	
	Set<Map.Entry<Student,String>> entrySet=tm.entrySet();
	
	Iterator<Map.Entry<Student,String>> it=entrySet.iterator();
	while(it.hasNext()){
		Map.Entry<Student,String> me=it.next();
		Student stu=me.getKey();
		String addr=me.getValue();
		sop(stu+"......"+addr);
	}
	}
	// 打印语句
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

// 按照学生姓名排序,当对象本身具有比较性,但还需另一种比较,
// 可以定义比较器,在集合初始化时传入比较器,当有两种比较方式时默认按照比较器方法排序
class StuNameComparator implements Comparator<Student>{
	public int compare(Student s1,Student s2){
		int num =s1.getName().compareTo(s2.getName());
		
		if(num==0)
			return new Integer(s1.getAge()).compareTo(s2.getAge());
		
		return num;
	}	
}

// 学生类,保证学生的唯一性
class Student implements Comparable<Student>{	
	private String name;
	private int age;
	
	public Student(String name,int age){
		this.name=name;
		this.age=age;
	}
	
	// 防止该对象往二叉树数据类型集合中存储报异常,应使该对象具备可比性
	public int compareTo(Student s){
		int num=new Integer(this.age).compareTo(new Integer(s.age));
		
		if(num==0)
			return this.name.compareTo(s.name);
		
		return num;
	}
	
	// 保证学生的唯一性
	public int hashCode(){
		return this.name.hashCode()+age*35;
	}
	
	public boolean equals(Object obj){
		
		if(!(obj instanceof Student))
			throw new ClassCastException("类型不匹配!");
		
		Student s=(Student)obj;
		
		return this.name.equals(s.name) && this.age==s.age;
	}
	
	public String getName(){
		return name;
	}
	
	public int getAge(){
		return age;
	}
	
	public String toString(){
		return name+":"+age;
	}
}

练习

核心思想原理图

import java.util.*;
/*
目标:
"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。

希望打印结果:
a(1)c(2)……

通过结果发现,每一个字母都有对应的次数。
说明字母和次数之间存在映射关系。

什么时候使用Map集合:
    当数据之间存在映射关系时,优先考虑Map集合。

思路:
1.将字符串转换成字符数组。因为要对每一个字母进行操作。
2.定义一个Map集合。而且打印结果字母有顺序,所以使用TreeMap集合。
3.遍历字符数组。
	将每一个字母作为键去查Map集合元素。
	如果返回null,将该字母和1存入到Map集合中。
	如果返回不是null,说明该字母在Map集合已经存在并有对应次数(值)。
	那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到Map集合中。原理:覆盖已有键对应的值。
4.将Map集合中的数据变成指定的字符串形式返回。
*/
class MapTest3{
	public static void main(String[] args){
		
		String s="sdfgzxcv,asdfxcv+df";
		
		String result=charCount(s);
		
		System.out.println(result);
		
	}
	
	public static String charCount(String str){
		
		char[] chs=str.toCharArray();
		
		TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
		
		int count=0;
		for(int x=0;x<chs.length;x++){
			// 检查该字符是否为字母,如果不是跳出本次循环
			if(!(chs[x]>='a' && chs[x]<='z' || chs[x]>='A' && chs[x]<='Z'))
				continue;
				
			Integer value=tm.get(chs[x]);
			
			if(value!=null)
				count = value;
			count++;
			tm.put(chs[x],count);
			
			count=0;
			
			/*// 繁复写法
			if(value==null){
				tm.put(chs[x],1);
			}else{
				value=value+1;
				tm.put(chs[x],value);
			}*/
		}
		
		// System.out.println(tm);
		
		StringBuilder sb=new StringBuilder();
		Set<Map.Entry<Character,Integer>> entrySet=tm.entrySet();
		Iterator<Map.Entry<Character,Integer>> it=entrySet.iterator();
		while(it.hasNext()){
			Map.Entry<Character,Integer> me=it.next();
			char key=me.getKey();
			int value=me.getValue();
			sb.append(key+"("+value+") ");
		}
		
		return sb.toString();
	}
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JAVA--Map集合详解 的相关文章

随机推荐

  • 【MATLAB傅里叶级数3D动画演示】

    傅里叶级数3D动画演示 编写环境 MATLAB2021b classdef Msg lt event EventData MSG 定义事件消息 event EventData子类 消息中封装有要发布的数据 Data 数据可以是任意类型 pr
  • Jmeter之接口测试流程详解

    前言 今天笔者呢 想给大家聊聊Jmeter接口测试流程详解 废话不多说直接进入正题 一 jmeter简介 Jmeter是由Apache公司开发的java开源项目 所以想要使用它必须基于java环境才可以 Jmeter采用多线程 允许通过多个
  • C#简单练习一

    namespace Demo练习 internal class Program static void Main string args 输入a b两个整数 编程求出a除以b得到的商和余数 输入 两行 只有两个整数 输出 输出只有一行 两个
  • 使用GPU训练(PyTorch demo)

    cuda 对网络模型 数据 损失函数这三种变量调用 cuda 来在GPU上进行训练 将网络模型在gpu上训练 model Model model model cuda 损失函数在gpu上训练 loss fn nn CrossEntropyL
  • PCL调错:合集

    1 error C4996 pcl visualization PointCloudColorHandler
  • QT-线程池

    在程序逻辑中经常会碰到需要处理大批量任务的情况 比如密集的网络请求 或者日志分析等等 一般会创建一个队列 用一个或者多个线程去消费这个队列 一般也要处理队列的加锁和解锁的问题 除非在设计时就能够做到专列专用 否则锁是不可避免的 而且在入队和
  • Kubernetes v1.26 配置默认存储 StorageClass

    Kubernetes v1 25 引入了一个 Alpha 特性来更改默认 StorageClass 被分配到 PersistentVolumeClaim PVC 的方式 启用此特性后 你不再需要先创建默认 StorageClass 再创建
  • vue所有UI库通用)tree-select 下拉多选(设置 maxTagPlaceholder 隐藏 tag 时显示的内容,支持鼠标悬浮展示更多

    如果可以实现记得点赞分享 谢谢老铁 1 需求描述 引用的下拉树形结构支持多选 限制选中tag的个数 且超过制定个数 鼠标悬浮展示更多已选中 2 先看下效果图 3 实现思路 首先根据API文档 先设置maxTagCount 最多显示多少个 t
  • networkx创建带权有向图,访问每个点的邻居节点(neighbor)和边权(weight)

    import networkx as nx G nx DiGraph 创建有向图 G add edge 1 2 weight 1 添加 带权边 weight表示边权 G add edge 1 3 weight 1 G add edge 3
  • eureka缓存

    AP系统 服务端 三级缓存 缓存 说明 一级 本地缓存 实时更新 客户端注册时数据保存到这 二级 读写缓存 实时更新 客户端注册 下线 故障时缓存失效 读取读写缓存找不到数据时 去一级缓存读取并保存到二级缓存 三级 读缓存 周期更新 默认3
  • watch的使用方法

    watch简单监听属性 监听对象就不要用这种写法 data return num 1 watch num newval oldval newval 是新值 oldval 是修改前的值 num有变化之后所执行的代码块 console log
  • 学习总结Q

    学习总结 学习内容 Java HashSet 学习产出 HashSet 基于 HashMap 来实现的 是一个不允许有重复元素的集合 HashSet 允许有 null 值 HashSet 是无序的 即不会记录插入的顺序 HashSet 不是
  • MySQL 的CASE WHEN 语句使用说明

    介绍mysql数据库中case when语句的用法 首先介绍case when语句的基础知识 然后提供了相关例子 1 mysql数据库中CASE WHEN语句 case when语句 用于计算条件列表并返回多个可能结果表达式之一 CASE
  • 【C++11智能指针】shared_ptr的初始化、拷贝构造和拷贝赋值、移动构造和移动赋值

    文章目录 1 智能指针概述 2 shared ptr的初始化 2 1 shared ptr和new结合使用 直接初始化 2 2 make shared函数 3 shared ptr的拷贝构造和拷贝赋值 4 shared ptr的移动构造和移
  • 函数名称前面加引用“&”或指针符号“*”的意思

    学习笔记 一 函数名称前面加引用符号 代表该函数返回值类型是引用 如 int operate 二 函数名称前面加指针符号 代表它是函数指针 函数指针是一个指向函数的指针 函数指针表示一个函数的入口地址 使用函数指针的好处就是在处理 在运行时
  • 解析敏捷开发流程之Scrum:3个角色、5个会议、12原则

    本文主要从Scrum的定义和目的 敏捷宣言 Scrum中的人员角色 Scrum开发流程 敏捷的12原则等几方面帮助大家理解Scrum敏捷开发的全过程 一 Scrum的定义和目的 Scrum是一个用于开发和维护复杂产品的框架 是一个增量的 迭
  • MySql在Windows下查看日志

    大体记录mysql查看日志的方法 并不具体 1 查看是否开启了日志 show variables like log bin value是ON表示已开启 如果没开启执行第二步 2 开启日志 在mysql的配置文件mysql ini中的 mys
  • react 开发环境下 解决 Uncaught ReferenceError: process is not defined 异常:

    react 开发环境下 解决 Uncaught ReferenceError process is not defined 异常 package json中添加 resolutions react error overlay 6 0 9 锁
  • 什么是AQS?

    AQS AbstractQueuedSynchronizer 是 Java 中用于构建同步器的抽象基类 它提供了一种强大的框架 使得可以相对容易地构建各种同步工具 如锁 信号量 倒计数器等 AQS 是 Java 并发包中的核心组件之一 它在
  • JAVA--Map集合详解

    特点 该集合存储键 key 值 value 对 一对一对往里存 而且要保证键 key 的唯一性 Map集合和Set集合很像 其实Set集合底层就是使用了Map集合 什么时候使用Map集合 当数据之间存在映射关系时 优先考虑Map集合 Map