RecyclerView学习笔记(1) ChildHelper.Bucket
来源:互联网 发布:csol刀战优化 编辑:程序博客网 时间:2024/06/01 09:44
- 简介
- toString方法
- set方法
- get方法
- clear方法
- countOnesBefore方法
- reset方法
- insert方法
- remove方法
- 总结
- 简介
简介
RecyclerView中的ChildHelper.Bucket是一个工具类,实现了类似List<Boolean>
的数据结构,从而达到减少内存占用的目的。
Bucket是一个链表结构,有两个字段:mData用于存储当前信息,next指向下一个数据
public static class Bucket { final static int BITS_PER_WORD = Long.SIZE; final static long LAST_BIT = 1L << (Long.SIZE - 1); long mData = 0;//当前数据 Bucket next;//指向下一个数据}
mData是long类型,存在64个bit位,每一个bit位可以是0或者1,代表true或false。这样一个mData可以存储64个(long类型的位数)true或false信息。相对于List<Boolean>
,而且是最多64位。当然,如果需要集合的大小超过了64,则相关的信息存储到了next中,这就是使用链表的作用了吧。
toString方法
链式调用next,打印mData的二进制字符串,不同的buckt用xx分隔(后面有使用示例)
@Override public String toString() { return next == null ? Long.toBinaryString(mData) : next.toString() + "xx" + Long.toBinaryString(mData); }
调用端代码:
Log.i(TAG,bucket.toString());//0 bucket.set(65); Log.i(TAG,bucket.toString());//10xx0
set方法
设置对应index位的bit为1(index从0开始)
public void set(int index) { if (index >= BITS_PER_WORD) {//如果index大于等于64,则相关信息设置到next中 ensureNext(); next.set(index - BITS_PER_WORD); } else { mData |= 1L << index; } }
调用端代码:
ChildHelper.Bucket bucket = new ChildHelper.Bucket();bucket.set(3);Log.i(TAG,bucket.toString());//1000
从结果可以看到:idex为3的位置的bit已经被设置成1了
get方法
判断index对应的bit是否为1,如果为1,返回true,否则返回false。
public boolean get(int index) { if (index >= BITS_PER_WORD) {//如果index大于等于64,则从next中获取 ensureNext(); return next.get(index - BITS_PER_WORD); } else { return (mData & (1L << index)) != 0; } }
调用端代码:
bucket.set(4);Log.i(TAG,bucket.toString());//10000boolean has4 = bucket.get(4);Log.i(TAG,"has4=" + has4);//has4=true
可以看到index为4的bit为1,就返回了true
clear方法
设置index对应的bit为0
public void clear(int index) { if (index >= BITS_PER_WORD) {//如果index大于等于64,则设置next中相应数据 if (next != null) { next.clear(index - BITS_PER_WORD); } } else { mData &= ~(1L << index); } }
调用端代码:
bucket.set(3); Log.i(TAG,bucket.toString());//1000 bucket.clear(3); Log.i(TAG,bucket.toString());//0
可以看到index为3对应的bit已经被设置成0
countOnesBefore方法
计算比index小的所有位数上bit为1的总个数。
例如 0001 1010,如果index为5,则结果为3;如果index为4,则结果是2
public int countOnesBefore(int index) { if (next == null) { if (index >= BITS_PER_WORD) { return Long.bitCount(mData); } return Long.bitCount(mData & ((1L << index) - 1)); } if (index < BITS_PER_WORD) { return Long.bitCount(mData & ((1L << index) - 1)); } else { return next.countOnesBefore(index - BITS_PER_WORD) + Long.bitCount(mData); } }
调用端代码:
bucket.set(4); Log.i(TAG,bucket.toString());//10000 boolean has4 = bucket.get(4); Log.i(TAG,"has4=" + has4);//has4=true bucket.set(3); bucket.set(2); Log.i(TAG,bucket.toString());//11100 int i = bucket.countOnesBefore(5); Log.i(TAG,"i=" + i);//i=3(前5位中bit为1的总数) int j = bucket.countOnesBefore(4); Log.i(TAG,"j=" + j);//j=2(前4位中bit为1的总数)
可以看到,如果当前bucket为11100,则countOnesBefore(5)为3,countOnesBefore(4)为2。
reset方法
重置,所有数据置为0
public void reset() { mData = 0; if (next != null) { next.reset(); } }
调用端代码:
bucket.set(65); Log.i(TAG,bucket.toString());//10xx0 bucket.reset(); Log.i(TAG,bucket.toString());//0xx0
insert方法
在index位置插入指定bit:value为true插入1,value为false插入0
public void insert(int index, boolean value) { if (index >= BITS_PER_WORD) {//如果index大于等于64,则在next中插入 ensureNext(); next.insert(index - BITS_PER_WORD, value); } else { final boolean lastBit = (mData & LAST_BIT) != 0; long mask = (1L << index) - 1; final long before = mData & mask;//小于index的数据 final long after = ((mData & ~mask)) << 1;//大于index的数据,已经左移一位,腾出当前位置 mData = before | after; if (value) { set(index);//value为ture插入1 } else { clear(index);//value为false插入0 } if (lastBit || next != null) { ensureNext(); next.insert(0, lastBit);//将当前bucket最高位的bit插入到next的index为0的位置上(实现左移操作) } } }
调用端代码:
bucket.reset(); Log.i(TAG,bucket.toString());//0xx0 bucket.set(6); bucket.set(5); Log.i(TAG,bucket.toString());//0xx1100000 bucket.insert(6,false); Log.i(TAG,bucket.toString());//0xx10100000(6和5之间插入一位,插入的值为0) bucket.insert(6,true); Log.i(TAG,bucket.toString());//0xx101100000(6和5之间插入一位,插入的值为0)
可以看到在index为6的位置上插入了指定bit,低于6的数据保持不变,大于等于6的数据左移了一位
remove方法
移除index对应位置的bit。低于index的所有数据保持不变,高于index的数据右移一位。
public boolean remove(int index) { if (index >= BITS_PER_WORD) {//如果index大于等于64,则在next中移除 ensureNext(); return next.remove(index - BITS_PER_WORD); } else { long mask = (1L << index); final boolean value = (mData & mask) != 0; mData &= ~mask;//index未bit置为0 mask = mask - 1; final long before = mData & mask;//小于index的数据 // cannot use >> because it adds one. final long after = Long.rotateRight(mData & ~mask, 1);//大于index的数据(已右移一位) mData = before | after; if (next != null) {//如果next存在 if (next.get(0)) {//如果next的index为0的bit为1 set(BITS_PER_WORD - 1);//设置当前最高位的bit为1(相当于右移一位) } next.remove(0);//next需要进行:删除index为0的操作 } return value; } }
调用端代码:
Log.i(TAG,bucket.toString());//0xx101100000(6和5之间插入一位,插入的值为0)bucket.remove(6);Log.i(TAG,bucket.toString());//0xx10100000(移除位置6的bit)
可以看到index为6的bit删除了,低于6的数据保持不变,高于6的数据全部右移了一位
总结
Bucket通过链表的数据结构和long类型可以存储64位bit为1或0的特性,实现了类似List<Boolean>
的数据结构,从而达到减少内存占用的目的。
- RecyclerView学习笔记(1) ChildHelper.Bucket
- RecyclerView机制解析: ChildHelper
- RecyclerView学习笔记
- RecyclerView学习笔记
- RecyclerView学习笔记
- android RecyclerView学习笔记
- RecyclerView学习笔记
- [学习笔记]Android RecyclerView
- 算法学习-Bucket排序
- MaterialDesign之RecyclerView学习笔记
- Android学习笔记之RecyclerView
- RecyclerView+CardView+SwipeRefreshLayout---学习笔记
- 算法学习之Bucket Sort
- MaterialDesign之RecyclerView学习笔记2
- Android学习笔记之RecyclerView详解
- 学习android(RecyclerView)个人笔记二
- 《第一行代码》RecyclerView学习笔记
- RecyclerView笔记
- express res.sendFile absolute path
- iOS 获取指定日期的时间(年、月、日、星期、时、分、秒等)
- Vue属性与方法
- socket编程(一)
- C++之强制转换运算符[转]
- RecyclerView学习笔记(1) ChildHelper.Bucket
- Tomcat的目录结构详细介绍(超全)
- python中字典按键或键值排序
- springmc采用.jpg为后缀名访问请求问题分析
- [LibreOJ β Round]ZQC的截图
- Scala基础—Map和Tuple操作示例
- python 图片显示几种办法
- FastText的词向量表征
- test