android中占容器比例,Android中的容器

List

java.util包提供了两种java

ArrayList

LinkedList

ArrayList比LinkedList经常使用不少,缘由是:

ArrayList查找更容易算法

ArrayList

ArrayList封装了一个数组Object[]数组

数组的初始化缓存 ArrayList array = new ArrayList();

封装一个空数组, {}安全 ArrayList array = new ArrayList(10);

封装一个大小为10的数组 new Object[10];

性能优化

数组如何实现扩容

数据结构

ArrayList.add/addAll都须要先进行扩容检查,

相似,并发 对象调用方法,要进行对象判空,

UI操做以前要进行,线程检查

扩容检查: size+增长的大小 与 数组.length 比较

计算数组扩容的数组长度:性能

首先,扩容至原数组大小的一倍,size+增长的大 小与其比较:

若是大于,扩容至原数组大小的一倍

若是小于,扩容至size+增长的大小;优化

private void grow(int minCapacity) {

// overflow-conscious code

int oldCapacity = elementData.length;

int newCapacity = oldCapacity + (oldCapacity >> 1);

if (newCapacity - minCapacity < 0)

newCapacity = minCapacity;

if (newCapacity - MAX_ARRAY_SIZE > 0)

newCapacity = hugeCapacity(minCapacity);

// minCapacity is usually close to size, so this is a win:

elementData = Arrays.copyOf(elementData, newCapacity);

}

扩容使用的是: Array.copyof(array, newLen)

removeAll如何实现

与remove()不一样,remove使用System.copy完成数组的 部分移动

而removeAll,使用的算法: ArrayList array1 = new ArrayList();

array1.addAll({0,3,5,7,3,6});

int[] array2 = {3,5,4};

array1.removeAll(array2);

首先,遍历array1中每一个元素,若元素 不在array2内,将计数位置的值设置为元素的值并将计 数+1;

遍历完成后,计数为数组剩余元素的个 数,将计数以后的元素清空.

算法详细:   0,3,5,7,3,6 ;

  遍历以后,计数为2,数组为0,7,6,7,3,6;

  清空以后,0,7,6,null,null,null;

trimToSize()

数组扩容后即便删除元素,数组的length也不会该改变,

意味着即便删除了某些元素数组占用的内存大小不会改变;

数组只会不断的增大,且出现大量null的元素.

trimToSize()方法用于改变数组的length,将为null的元素释放掉,等待GC

这也是防止内存浪费的一种方式,当ArrayList经历了屡次删除操做以后,使用trimToSize(),避免内存浪费.

trimToSize()使用Array.copyof()来改变数组的length

总结

ArrayList本质上维护了一个数组,也就意味者它具备数组的优缺点:增删难,查找易

LinkedList

Node的数据结构 Node {

E element;

Node prev;

Node next;

}

基本结构 Node first, last

Linked是双向链表,first,last指向表头,表尾

总结

LinkedList是一个Deque,双向链表,

增删易,查找难,形成在编码中不多使用

Map

java.util包提供了两种Map:

1.HashMap

2.TreeMap

Android为了性能优化,提供了HashMap的替代品:

1.ArrayMap

2.SparseMap

它俩能够在数据量都在千级之内的状况下,

若是key的类型为int,使用SparseMap,

若是key的类型为其它类型,使用ArrayMap

HashMap相比TreeMap更经常使用

HashMap

数据结构

Node的数据结构: Node {

int hash;

K key;

V value;

Node next;

}

基本数据结构: Node[] table;

float loadFoctor;//默认值0.75f

int threshold;

能够看出HashMap的数据结构是数组+链表

扩容

何时扩容

当调用put/putAll时,实际上都是调用putVal方法

先建立Node,再查看新的Node放入数组,仍是链表;

当++size>threshold,则须要扩容

table如何扩容

它的扩容包含两个步骤: 1. 肯定扩容的大小;

2. 如何移动元素,包含数组中的元素与链表中的元素;

肯定扩容的大小:

threshold默认值 = 16*0.75f=12

每次扩容,

先建立一个threadhold大小的数组,赋给tble,也就是扩容至threadhold

再,threadhold = threadhold <<1,扩大一倍

如何移动元素,包含数组中的元素与链表中的元素:

1.若是元素只在数组里,而没有链表:

新的位置是 e.hash&(newCap-1)

2.元素在链表上:

根据(e.hash & oldCap) == 0 决定是在原位置仍是在原位置+oldCap上

链表可能会分为两部分

TreeMap

数据结构

TreeMapEntry的数据结构 TreeMapEntry {

K key;

V value;

TreeMapEntry left;

TreeMapEntry right;

TreeMapEntry parent;

}

TreeMap的数据结构: TreeMapEntry root;

Comparator super K> comparator;

TreeMap其实是红黑二叉树

SparseArray

数据结构 int[] mKeys;

Object[] mValues;

总结

官方推荐去使用SparseArray去替换HashMap,

牺牲了部分效率换来内存

ArrayMap

LinkedHashMap

能够看做HashMap+LinkedList,用于保证插入顺序

通常用于做为缓存

Java中的线程安全的容器

同步容器

Vector

HashTable

并发容器

用于读写分离,实现读并发,写同步

并发的不一样策略:

1.Blocking容器

2.CopyOnWrite容器

3.Concurrent容器

Blocking容器

并发策略:

用于解决限制容量的容器的存取问题

相似生产者-消费者

容器为空时,阻塞取线程

容器满时,阻塞存线程

CopyOnWrite容器

并发策略:

写时赋值,即添加元素时,先复制整个容器,添加到复制的容器中,

再将容器引用指向复制的容器,达到读的最大并发;

适用于读多写少的状况;

Concurrent容器

并发策略:

使用分段锁,首先将容器分红多段,每段使用不一样的锁,对不一样段达到读写并发,相同段读并发,写同步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值