SafeIterableMap

Jetpack-Lifecycle组件-SafeIterableMap解析 Jetpack-Lifecycle组件-SafeIterableMap解析 文章目录Jetpack-Lifecycle组件-SafeIterableMap解析概述`SafeIterableMap`核心方法FastSafeIterableMap使用`SafeIterableMap``FastSafeIterableMap`源码解析`SafeIterableMap``Put`操作`Get`操作`remove`操作迭代器`ListIterator`抽象迭代器`AscendingIterator`升序迭代器`Asc 阅读详情

SafeIterableMap

LinkedList, which pretends to be a map and supports modifications during iterations. It is NOT thread safe.

  1. 其底层用时链表(双向)实现,pretends to be (假装) map.
  2. 支持在迭代过程中直接修改(调用其自身的put 或者remove),比如删除,添加 。其他集合需要通过其Iterator 来实现对集合的修改。否则会抛出ConcurrentModificationException,虽然Iterator 支持迭代过程中删除,但并不是所有的Iterrator都支持迭代过程中添加,
  3. 线程不安全
  4. 一般不能直接在项目中使用,Studio 会变红,但是不影响正常编译和使用,可以通过添加注解@SuppressLint("RestrictedApi") 来抑制警告
  5. 在迭代过程中不能像其他集合一样调用 Iterator 的remove 方法,其默认实现是抛出 UnsupportedOperationException

概述

SafeIterableMap 他是google工程师在 Androidx 中提供的一个简单数据结构,非线程安全,以键值对方式存取数据,看似一个map,其底层是一个双向链表,每一个键值对被包装成一个 Entry<K,V> 被保存。支持双向遍历,并且支持在迭代过程中直接对集合的修改(直接调用map的put 或者remove方法,比如添加删除,不能调用Iteratorr的remove方法)。其他集合在迭代过程中只能通过Iterator进行修改操作。并且不是所有的Iterator 都支持添加,只有List 中的ListIterator 支持添加操作,当然SafeIterableMap 支持迭代过程中支持修改操作,是因为他自己实现的Iterator 支持了, SafeIterableMap 一共有三个 Iterator 实现类,AscendingIterator (顺序迭代),DescendingIterator (反向迭代),IteratorWithAdditions(顺序迭代,支持添加操作),三个都实现了SupportRemove 接口,并且实现了SupportRemove接口中的supportRemove方法,该方法就是用来当 SafeIterableMap 中Entry 被删除时,让Iterator 感知到,使其把对SafeIterableMap 的修改同步到Iterator 中。因此 这三个Iterator 都支持迭代过程中删除,但是只有IteratorWithAdditions支持迭代过程中添加新的。其他两个Iteratro 在迭代的时候调用SafeIterableMap 的put方法不会抛出异常,只是不能迭代到新put的数据而已。

因为我们到知道其他集合不支持在迭代过程中直接调用集合的修改方法对集合进行修改,就是因为集合中有一个变量 modCount 记录了集合修改的次数,每修改一次 modCount 都会加一,迭代集合时Iterator 在被创建出来(new)的时记录了集合当前的一个状态,比如集合的修改次数modCount ,集合的size等,在调用Iterator方法进行迭代的时候会去判断Iterator 中记录的modCount 次数是否和集合中最新的modCount 是否相等,如果相等意味着集合没有发生修改,如果不相等意味着集合一定发生了修改,直接抛出了ConcurrentModificationException。

File Structure

在这里插入图片描述

源码解析



/**
 * LinkedList, which pretends to be a map and supports modifications during iterations.
 * It is NOT thread safe.
 * 一个底层用链表实现的类似与Map的集合,并且支持在迭代过程中对map 进行修改
 */

//这个注解导致了我们在项目代码中使用此api studio 会有警告提示,但不影响编译和正常运行。可以通过注解消除警告
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP_PREFIX)
public class SafeIterableMap<K, V> implements Iterable<Map.Entry<K, V>> {
   
   

		//链表的头结点
    Entry<K, V> mStart;
  	// 链表的尾结点
    private Entry<K, V> mEnd;
  	
  

		/**
		 * using WeakHashMap over List<WeakReference>, so we don't have to manually remove
		 * WeakReferences that have null in them.
		 *
		 * 使用WeakHashMap代替List<WeakReference>,这样就不用再手动删除WeakReferences,
		 * 意思就是说,如果用List<WeakReference> 存储Iterator,其结构将是这样的List<WeakReference<Iterator>>
		 * 那么当Iterrator被回收后,还需要手动从List中把WeakReference这个对象删,用WeakHashMap则省掉了这个操作.
		 * 
		 * 该Map用来保存迭代时new 出来的迭代器,以便在调用 sefaIterableMap.remove()方法时通知到所有迭代器,更新迭代
		 * 器里面的状态,使迭代器能够响应 map 的修改,比如你在迭代过程中对map删除了某一个key,那么在迭代过程中,将不会获取
		 * 道这个entry.如果是使用InteratorWithAdditions这个迭代器,在迭代过程中还可以调用map.putIfAbsend方法添加一个
		 * 新的entry,别切会在迭代过程中会被输出
		 */

    private WeakHashMap<SupportRemove<K, V>, Boolean> mIterators = new WeakHashMap<>();
  
  	// map 中 元素的个数,也即是链表的长度
    private int mSize = 0;

  /**
   * 从头开始遍历链表中的每一个Eetry,如果entry.key equals 传入的key
   * 则返回该entry。如果链表为null,或者找不到对应的entry 返回null
   */
    protected Entry<K, V> get(K k) {
   
   
        Entry<K, V> currentNode = mStart;
        while (currentNode != null) {
   
   
            if (currentNode.mKey.equals(k)) {
   
   
                break;
            }
            currentNode = currentNode.mNext;
        }
        return currentNode;
    }

    /**
     * 如果不存在则保存,返回null
     * 如果已经存在则返回存在的旧值
     */
    public V putIfAbsent(@NonNull K key, @NonNull V v) {
   
   
        Entry<K, V> entry = get(key);
        if (entry != null) {
   
   
            return entry.mValue;
        }
        put(key, v);
        return null;
    }
		
  	/**
  	 * 把key,value 包装成 Entry 插入到链表尾部,size++
  	 * 并返回新保存entry对象
  	 *
  	 */
    protected Entry<K, V> put(@NonNull K key, @NonNull V v) {
   
   
        Entry<K, V> newEntry = new Entry<>(key, v);
        mSize++;
        if (mEnd == null) {
   
    // 表示链表为null,首尾都指向这个newEntry
            mStart = newEntry;
            mEnd = mStart;
            return newEntry;
        }
				// 更新尾结点,使newEntry为新的尾结点
        mEnd.mNext = newEntry;
        newEntry.mPrevious = mEnd;
        mEnd = newEntry;
        return newEntry;

    }

    /**
     * Removes the mapping for a key from this map if it is present.
     *
     * @param key key whose mapping is to be removed from the map
     * @return the previous value associated with the specified key,
     * or {@code null} if there was no mapping for the key
     *
     *  从链表中移除一个key对应的entry,如果不存在返回null.如果存在返回这个entry.value
     */
    public V remove(@NonNull K key) {
   
   
      
        Entry<K, V> toRemove = get(key); //从头开始遍历链表,找到一个与key对应的entry
        if (toRemove == null) {
   
   
            return null; // 如果找不到,返回null
        }
        mSize--; // 如果找到了,size--
      
      	// 遍历还未被回收的iterator,通知其要删除一个entry,
      	// 这就是safeIterableMap 支持迭代过程中删除的关键代码
        if (
使用 FastAPI 和 LangGraph 构建生产级智能体 AI 系统 这是一本关于使用 FastAPI 和 LangGraph 构建生产级智能体 AI 系统的详细书籍,全文约 10 万字。《Production-Grade Agentic AI System Design and Implementation: Building Agentic AI Systems Using FastAPI and LangGraph》随着人工智能(AI)技术的迅猛发展,智能体(Agent)作为能够自主感知、推理、决策和行动的实体,正逐渐成为构建复杂智能系统的核心。从个性化推荐、客户服务到 阅读详情

相关推荐

告别抖动与滞后:深入博能传动伺服DSC功能,用105报文提升多轴同步性能

本文深入解析博能传动伺服DSC功能如何通过105报文实现多轴同步性能提升,有效解决工业自动化中的抖动与滞后问题。详细介绍了DSC技术原理、105报文实现机制及多轴同步工程实践,帮助工程师优化伺服系统性能,实现绝对齿轮同步。

weixin_30394981的博客 184

OpenVPN 新增 windows 客户端

虚拟私人网络(Virtual Private Network,简称VPN)是一种网络技术,它允许用户通过公共网络(如互联网)建立一个安全的连接通道。本文介绍如何添加 windows 客户端。

利昂的技术存档 3769

MSTAR数据集下载地址及处理方法

首先感谢博主冯子材提供下载的百度网盘地址。 在这里为了防止侵权,特此鸣谢,并给出其博客地址。 地址中有MSTAR百度网盘下载地址和需要使用的数据介绍,其中百度网盘中有数据转换工具 https://blog.youkuaiyun.com/taifengzikai/article/details/80600355 工具使用 因为下载得到的数据是二进制文件,需要使用官方提供的工具进行转换,可将其转换为jpeg。 有...

KamenRider 1万+

手把手教你用DCA1000EVM解析IWR6843毫米波雷达数据(附MATLAB代码)

本文提供了一份详尽的实战指南,手把手教你使用DCA1000EVM采集并解析TI毫米波雷达IWR6843的原始数据。内容涵盖硬件连接配置、mmWave Studio参数设置、LVDS数据流结构解析,并附有核心MATLAB代码,详细演示了从原始二进制文件到距离-速度谱的信号处理全链路,帮助开发者快速掌握数据解析与处理的关键步骤。

terraform7cloud的博客 227

声品质粗糙度matlab,声品质的应用分析方法

声品质的应用分析方法2016-04-05 09:18:57阅读次数:14198摘要:声品质分析在噪声的主观评价方面已经得到越来越多的应用。本文比较了声品质分析与传统计权声级的区别,并介绍了在声品质分析的实际应用中,针对稳态信号、非稳态信号的几种不同分析方法,以及各分析方法的要求和特点。关键词:声品质,响度,尖锐度,粗糙度,波动度1前言传统评价噪声的方法主要为计权声压级,用以反映声音的大小。但是人耳...

weixin_30767323的博客 2438

MongoDB分布式事务实现:两阶段提交、日志复制与冲突解决

MongoDB分布式事务机制解析 本文深入剖析了MongoDB 4.0+版本的分布式事务实现原理,重点分析了其在跨文档/跨集合/跨分片场景下的数据一致性解决方案。核心内容包括: 底层机制:采用改进的两阶段提交协议,通过oplog日志复制实现无中心协调器的事务管理,结合WiredTiger存储引擎和锁机制保障ACID特性。 创新设计:将传统2PC的中心协调功能分散到Primary节点,利用oplog作为事务状态记录,实现自动故障恢复和60秒超时回滚机制。 性能优化:针对大事务、写冲突等常见问题,提出拆分微事务

数据知道的博客 1261

ZooKeeper 实战:使用 Docker Compose 部署 ZooKeeper 集群

ZooKeeper是一个开源的分布式协调服务,用于管理大型分布式系统中的数据。它由Apache软件基金会提供,最初是Hadoop的一个子项目,但后来发展成为一个独立的顶级项目。ZooKeeper提供的一致性协调服务对于构建分布式应用和服务非常重要,特别是在需要精确的领导选举、配置管理、命名服务、分布式同步和提供分布式锁等功能时。

SmartSi 1541

【异常】API 速率限制报错问题全流程排查与解决指南 API rate limit reached. Please try again later.

摘要: 本文针对大模型API开发中常见的速率限制报错("API rate limit reached")提供全流程解决方案。首先解析该报错的本质是服务端对高频调用的保护机制,通过三步排查法确认根因:客户端请求频率超出账户阈值。提出三级解决方案:1)临时等待限流周期重置;2)升级付费账户提高调用配额;3)构建多模型容灾架构实现自动切换。建议生产环境优先采用容灾方案,通过备用API节点保障业务连续性,同时平衡不同模型服务的成本与性能。

奶爸的编程之路,也就一周冷个三天 1432

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

上一篇: Android Studio 打造一个适合自己开发环境-- Distraction Free Mode
下一篇: 带你详细了解 Android Lifecycle
皮克桃在写代码
博客等级 码龄12年 51粉丝 24原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮克桃在写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值