数据结构 学习

外部学习资料地址

ArrayList(数组)

一、描述
	1. ArrayList 是最常用的List 实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。
	2. 数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中。
	3.  当从ArrayList 的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
// arrayList 的 add 方法
public boolean add(E e) {
		// 确定ArrayList的容量大小 如果需要扩容 在这里 扩容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        // 长度 ++ 并赋值
        elementData[size++] = e;
        return true;
    }
二. 线程安全问题
	有两个 先上代码
	1. 在多个线程进行add操作时可能会导致elementData数组越界
		1. 列表大小为9,即size=9
		2. 线程A开始进入add方法,这时它获取到size的值为9,调用ensureCapacityInternal方法进行容量判断。
		3. 线程B此时也进入add方法,它获取到size的值也为9,也开始调用ensureCapacityInternal方法。
		4. 线程A发现需求大小为10,而elementData的大小就为10,可以容纳。于是它不再扩容,返回。
		5. 线程B也发现需求大小为10,也可以容纳,返回。
		6. 线程A开始进行设置值操作, elementData[size++] = e 操作。此时size变为10。
		7. 线程B也开始进行设置值操作,它尝试设置elementData[10] = e,而elementData没有进行过扩容,它的下标最大为9。于是此时会报出一个数组越界的异常ArrayIndexOutOfBoundsException.
	2. 一个线程的值覆盖另一个线程添加的值
		1. 列表大小为0,即size=0
		2. 线程A开始添加一个元素,值为A。此时它执行第一条操作,将A放在了elementData下标为0的位置上。
		3. 接着线程B刚好也要开始添加一个值为B的元素,且走到了第一步操作。此时线程B获取到size的值依然为0,于是它将B也放在了elementData下标为0的位置上。
		4. 线程A开始将size的值增加为1
		5. 线程B开始将size的值增加为2
  1. 多线程情况下 操作同一个集合

Vector(数组实现,线程同步)

  1. Vector 与ArrayList 一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList 慢。

LinkList(链表)

  1. LinkedList 是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。
  2. 另外,他还提供了List 接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

解决线程不安全的问题

解决 线程不安全的问题  都可以用
 1. Collections.synchronizedList();
 	Collections.synchronizedSet();
 2. 使用 Vector
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值