JAVA学习日记(17)——Map和Set

本文介绍了Map和Set在Java中的应用,包括Map.Entry的使用、TreeMap与HashMap的区别以及Set的特性。重点讨论了二叉搜索树和哈希表的概念、性能分析,特别是哈希冲突的避免与解决方法,如负载因子调节和开放定址法。
摘要由CSDN通过智能技术生成

1.搜索

1.1 概念及场景

Map和set是一种专门用来进行搜索的容器或者数据结构,其搜索的效率与其具体的实例化子类有关

我们之前学过的搜索方式有:

  1. 直接遍历,时间复杂度为O(N),元素如果比较多效率会非常慢
  2. 二分查找,时间复杂度为O(logN) ,但搜索前必须要求序列是有序

上述排序比较适合静态类型的查找,即一般不会对区间进行插入和删除操作了,而现实中业务的查找比如:

  1. 根据姓名查询考试成绩
  2. 通讯录,即根据姓名查询联系方式
  3. 不重复集合,即需要先搜索关键字是否已经在集合中

可能在查找时进行一些插入和删除的操作,即动态查找,那上述两种方式就不太适合了,因此本章介绍的Map和Set是一种适合动态查找的集合容器

1.2 模型

一般把搜索的数据称为关键字(Key),和关键字对应的称为值(Value),将其称之为Key-value的键值对,所以模型会有两种:

  1. 纯 key 模型,比如:
    ① 有一个英文词典,快速查找一个单词是否在词典中
    ② 快速查找某个名字在不在通讯录中
  2. Key-Value 模型,比如:
    ① 统计文件中每个单词出现的次数,统计结果是每个单词都有与其对应的次数:<单词,单词出现的次数>
    ② 梁山好汉的江湖绰号:每个好汉都有自己的江湖绰号

而之前在刚讲集合框架的时候我们说Map中存储的就是key-value的键值对,现在又告诉大家Set中只存储了Key

2.Map的使用

2.1 关于Map的说明

Map是一个接口类,该类没有继承自Collection,该类中存储的是<K,V>结构的键值对,并且K一定是唯一的,不能重复

2.2 关于Map.Entry<K, V>的说明

Map.Entry<K, V> 是Map内部实现的用来存放<key, value>键值对映射关系的内部类,该内部类中主要提供了<key, value>的获取,value的设置以及Key的比较方式

例如现在给定一个有10万个数据的数组,打印出其中重复的数字和重复的次数

代码示例:

public class TestDemo {
   
	public static void main(String[] args) {
   
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        int[] arr = new int[100000];
        Random random = new Random();
        //生成一个随机数组
        for (int i = 0; i < arr.length; i++) {
   
            int num = random.nextInt(100000);
            arr[i] = num;
        }
        //1.遍历数组
        //key值放数组元素
        //value值放元素出现的次数
        for (int val:arr) {
   
        	//元素在map中还未重复
            if (hashMap.get(val) == null) {
   
                hashMap.put(val,1);
            }else {
   
            	//存在则让次数加1
                int tmp = hashMap.get(val)+1;
                hashMap.put(val,tmp);
            }
        }
		//打印每个重复的数字和次数
        for (Map.Entry<Integer,Integer> entry:hashMap.entrySet()) {
   
            if (entry.getValue() > 1) {
   
                System.out.println("重复的数字:" + entry.getKey() + " 次数:" + entry.getValue());
            }
        }
    }
}

2.3 Map的常用方法说明

方法 解释
V get(Object key) 返回 key 对应的 value
V getOrDefault(Object key, V defaultValue) 返回 key 对应的 value,key 不存在,返回默认值
V put(K key, V value) 设置 key 对应的 value
V remove(Object key) 删除 key 对应的映射关系
Set keySet() 返回所有 key 的不重复集合
Collection values() 返回所有 value 的可重复集合
Set<Map.Entry<K, V>> entrySet() 返回所有的 key-value 映射关系
boolean containsKey(Object key) 判断是否包含 key
boolean containsValue(Object value) 判断是否包含 value

注意:

  1. Map是一个接口,不能直接实例化对象,如果要实例化对象只能实例化其实现类 TreeMap 或者 HashMap
  2. Map中存放的键值对的key是唯一的,value是可以重复的
  3. Map中插入键值对时,key值不能为空,否则会报出空指针异常,value可以为空
  4. Map中的key可以全部分离出来储存到Set中去进行访问,因为key值不能重复
  5. Map中的value可以全部分离出来储存到Collection的任何一个子集合中,value可以重复
  6. Map中的key值不能直接修改,value值可以直接修改,如果要修改key的值,必须先将key值删掉,再插入新的key值
  7. TreeMap 和 HashMap 的区别
Map底层结构 TreeMap HashMap
底层结构 红黑树 哈希桶
插入/删除/查找时间 O(logN) 复杂度 O(1)
是否有序 关于Key有序 无序
线程安全 不安全 不安全
插入/删除/查找区别 需要进行元素比较 通过哈希函数计算哈希地址
比较与覆写 key必须能够比较,否则会抛出ClassCastException异常 自定义类型需要覆写equals和hashCode方法
应用场景 需要Key有序场景下 Key是否有序不关心,需要更高的时间性能

2.4 TreeMap的使用案例

下面用TreeMap的实例给大家演示一下上面的方法的使用

代码示例:

import java.util.TreeMap;
import java.util.Map;
 public static void TestMap1(){
   
 	Map<String, String> m = new TreeMap<>();
 	// put(key, value):插入key-value的键值对
 	// 如果key不存在,会将key-value的键值对插入到map中,返回null
 	m.put("林冲", "豹子头");
 	m.put("鲁智深", "花和尚");
 	m.put("武松", "行者");
 	m.put("宋江", "及时雨");
 	String str = m.put("李逵", "黑旋风");
 	System.out.println(m.size());
 	System.out.println(m);
 	
 	// put(key,value): 注意key不能为空,但是value可以为空
 	// key如果为空,会抛出空指针异常
 	//m.put(null, "花名");
 	str = m.put("无名", null);
 	System.out.println(m.size());
 	
 	// put(key, value):
 	// 如果key存在,会使用value替换原来key所对应的value,返回旧value
 	str = m.put("李逵", "铁牛");
 	
 	// get(key): 返回key所对应的value
 	// 如果key存在,返回key所对应的value
 	// 如果key不存在,返回null
 	System.out.println(m.get("鲁智深"));
 	System.out.println(m.get("史进"));
 	
 	//GetOrDefault(): 如果key存在,返回与key所对应的value,如果key不存在,返回一个默认值
 	System.out.println(m.getOrDefault("李逵", "铁牛"));
 	System.out.println(m.getOrDefault("史进", "九纹龙"));
 	System.out.println(m.size
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java中,也有类似于C++ STL中的mapset的容器。Java中的mapset都是基于接口实现,常用的实现类有HashMap、TreeMap、LinkedHashMap等。常用的set实现类有HashSet、TreeSet、LinkedHashSet等。 Map接口和Set接口的主要区别在于,Map接口用于存储键值对,而Set接口用于存储不重复的元素。Map接口提供了put()、get()、remove()等方法,Set接口提供了add()、remove()、contains()等方法。 HashMap是一种基于哈希表实现的Map接口的实现类,它提供了快速的查找、插入和删除操作,查找、插入和删除操作的时间复杂度都为O(1)。HashMap中的键和值都可以为null,但HashMap不保证元素的有序性。如果需要按照元素的插入顺序访问元素,可以使用LinkedHashMap。 TreeMap是一种基于红黑树实现的Map接口的实现类,它保证了元素的有序性,元素按照键的自然顺序或比较器顺序进行排序。TreeMap的查找、插入和删除操作的时间复杂度都为O(logN)。 HashSet是一种基于哈希表实现的Set接口的实现类,它提供了快速的查找、插入和删除操作,查找、插入和删除操作的时间复杂度都为O(1)。HashSet不保证元素的有序性,元素可以为null。 TreeSet是一种基于红黑树实现的Set接口的实现类,它保证了元素的有序性,元素按照自然顺序或比较器顺序进行排序。TreeSet的查找、插入和删除操作的时间复杂度都为O(logN)。 LinkedHashSet是一种基于哈希表和链表实现的Set接口的实现类,它保证了元素的插入顺序,同时提供了快速的查找、插入和删除操作。LinkedHashSet的查找、插入和删除操作的时间复杂度都为O(1)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值