码迷,mamicode.com
首页 > 其他好文 > 详细

黑马程序员-ArrayList集合深入学习

时间:2015-08-26 09:27:39      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:

------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------

ArrayList集合

  1. 创建ArrayList

ArrayList类集成了AbstractList

ArrayList中有两个构造方法(方法名相同,方法参数不同叫做重载),默认构造方法通过调用ArrayListint)来事项ArrayList的创建,传入的值为10

技术分享

  1.  

技术分享

 

因为ArrayList类继承了AbstractList类,其中super调用了父类的默认构造方法,父类的该方法为一个空的方法(只有方法的声明,没有方法的实现),因此这段代码中最关键的是实例化了一个Object的数组,并将此数组付给了当前实例的elementData属性,Object的大小为传入的参数值,因此在调用空狗仔方法的时候,会创建一个大小为10Object数组,因此可以看到ArrayList采用数组的方式来存放对象

技术分享

  1.  
    1. 插入对象:add(E)

  • Add方法的实现

当调用add方法时候,首先基于ArrayList中已有的元素数量+1,产生一个名为minCapacity的变量,然后比较此值和Object数组的大小,如果此值大于Object数组值,那么先将当前的Object数组复制给一个数组对象,接着产生一个新的数组的容量值,此值的计算方法为当前数组值*1.5+1,如果得出的容量值仍然小于minCapacity,那么就以minCapacity作为新的容量值,在得出这个容量值后,调用ArrayList.copyOf来生成新的数组对象,如果想调整容量的增长策略,可集成ArrayList并覆盖ensureCapacity方法即可。

  • ArrayList.copyOf方法的实现

首先创建一个新的数组对象,该数组对象的类型和之前ArrayList中元素类型一直,如果是Object类型,则直接通过new Object[newLenth]的方式来创建,如果不是Object类型,则通过Array.newInstance调用native方法创建相同类型的数组,在创建完新的数组对象后,调用System.arraycopy通过native方法将之前数组中的对象复制到新的数组中

  • AddintE)方法的实现

将元素直接插入指定的int位置,这个方法的实现首相要确保插入的位置是目前数组中存在的,之后还要确保数组的容量够用,在完成这些动作之后,和add(E)的不同的地方就是他要将当前的数组对象进行一次复制,即将目前index以及其后的数据都往后挪动以为,然后才能将指定的index位置的赋值为传入对象,可见这中方式要多付出一次复制数组的代价。

  • SetintE

替换指定位置的对象,首先会检查传入的位置是否小于当前数组的长度,此方法的返回值为替换之前的当前位置的内容

技术分享

  1.  

技术分享

  1.  
  • AddAll(Collection<? extends E> c)

    实现方法和add方法相似

  1. 删除对象:remove(E)

当执行此方法时候,ArrayList首先判断对象是否为null,如果为null,则遍历数组中已经有值的元素,并比较是否为null,如果为null则调用fastRemove来删除相应位置的对象,fastRemove方法的实现方式为将index后的对象往前复制一位,并将数组中的最后一个设置为null,即释放了对此对象的引用,此方法返回truefalse

如果传入元素不为null,唯一的不同在于通过Eequals来比较元素的值是否相同,如果相同则认为是需要删除对象的位置,则调用fastRemove方法来完成删除,此方法返回truefalse

还提供了removeindex)方法来删除指定的对象,此方法比remove(e)多了一个数组范围的检测,但少了对象位置的查找,因此性能会更好,此方法返回删除的元素

技术分享

  1. Remove方法 技术分享
  2. fastRemove方法代码

技术分享

  1. Remove(index)方法
    1. 获取单个对象:get(index)

传入参数为数组中元素的位置,然后进行数组长度的验证,然后返回数组中此位置的对象

技术分享

  1. Get(index)方法
    1. 遍历对象:iterator()

Iterator方法有ArrayList的父类AbstractList实现,当每次调用iterate方法时,都会创建一个新的AbstractList内部类对象itr的实例,当调用此实例的hasNext方法时候,比较当前指向的数组的位置是否和数组中已有的元素大小相等,如相等则返回false,否则返回true

  1. 判断对象是否存在:contains(E)

方法的实现为遍历整个ArrayList中已经存在的元素,如果Enull,则直接判断已有元素是否为null,如为null,则返回true,如E不为null,则通过E.equals进行判断是否相等

IndexOf为从前往后查找

lastIndexOf为从后往前查找

技术分享

  1. Contains(E)方法

技术分享

  1. lastIndexOf方法
    1. 注意要点

  • ArrayList是基于数组方式实现的,无容量的限制
  • ArrayList在执行插入元素时可能要扩展,在删除元素时并不会减少数组的容量(如果希望缩小数组容量,可以调用ArrayListtrimToSize方法),在查找元素的时候,对非null的元素采用equals方式进行寻找
  • ArrayList是非线程安全的

    在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;

    而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值

线程不安全测试代码

import java.util.ArrayList;

import java.util.List;

 

public class Demo implements Runnable {

    List<String> list1 = new ArrayList<String>(1);// not thread safe

 

public void run() {

try {

            Thread.sleep((int)(Math.random() * 2));

        }

catch (InterruptedException e) {

e.printStackTrace();

        }

list1.add(Thread.currentThread().getName());

    }

 

public static void main(String[] args) throws InterruptedException {

        ThreadGroup group = new ThreadGroup("testgroup");

        Demo t = new Demo();

for (int i = 0; i < 10000; i++) {

            Thread th = new Thread(group, t, String.valueOf(i));

th.start();

        }

        

while (group.activeCount() > 0) {

            Thread.sleep(10);

        }

        System.out.println();

        System.out.println(t.list1.size()); // it should be 10000 if thread safe collection is used.

    }

}

黑马程序员-ArrayList集合深入学习

标签:

原文地址:http://www.cnblogs.com/itheimazl/p/4759306.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!