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

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

ArrayList集合

  1. 创建ArrayList

ArrayList类集成了AbstractList类

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

  1.  

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

    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方法将之前数组中的对象复制到新的数组中

  • Add(int,E)方法的实现

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

  • Set(int,E)

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

  1.  

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

    实现方法和add方法相似

  1. 删除对象:remove(E)

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

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

还提供了remove(index)方法来删除指定的对象,此方法比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中已经存在的元素,如果E为null,则直接判断已有元素是否为null,如为null,则返回true,如E不为null,则通过E.equals进行判断是否相等

IndexOf为从前往后查找

lastIndexOf为从后往前查找

  1. Contains(E)方法

  1. lastIndexOf方法

    1. 注意要点

  • ArrayList是基于数组方式实现的,无容量的限制
  • ArrayList在执行插入元素时可能要扩展,在删除元素时并不会减少数组的容量(如果希望缩小数组容量,可以调用ArrayList的trimToSize方法),在查找元素的时候,对非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.

}

}

时间: 2024-11-06 23:12:35

黑马程序员-ArrayList集合深入学习的相关文章

黑马程序员------Java集合框架学习总结

Java培训.Android培训.iOS培训..Net培训.期待您的交流 一.综述 所有集合类都位于java.util包下.集合中只能保存对象(保存对象的引用变量).(数组既可以保存基本类型的数据也可以保存对象). Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口,这两个接口又包含了一些接口或实现类. 二.Collection接口 Collction: List:有序(元素存入集合的顺序和取出的顺序一致),元素都有索引.

黑马程序员——JAVA集合框架学习总结

------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- www.itheima.com 要学好java的集合框架,必须掌握此图: Java集合框架很全面,从大的来说.它包括两种类型: 1.一种是以collection为根接口的集合. 2.另一种是由map为根接口的<key,value>的“图”. 而collection之下的set接口和list接口又有不同: 1.Set 接口继承 Collection,但不允许重复,使用自己内部的一个排列机制.

黑马程序员_集合

集合1.集合和对象数组的区别: 数组的长度不可变,集合的可变: 数组可以存储基本数据类型和对象,集合只能存储对象. 集合的框架图 集合派系的顶层接口Collection1.Collection集合存储对象的方法: add(E e)将元素存储到集合中 addAll(Collection c)将一个集合添加到另外的集合中2.Collection集合提取对象的方法: 通过迭代器iterator中的方法:hasNext()和next()来取出 Iterator it=new iterator(); wh

黑马程序员_JAVA 基础加强学习笔记

一.面向对象 (一)继承  1.继承的好处: (1) 提高了代码的复用性. (2) 让类与类之间产生了关系,提供了另一个特征多态的前提. 注意: 子类中所有的构造函数都会默认访问父类中的空参数的构造函数,因为每一个子类构造内第一行都有默认的语句super();  如果父类中没有空参数的构造函数,那么子类的构造函数内,必须通过super语句指定要访问的父类中的构造函数. 如果子类构造函数中用this来指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类中的构造函数. 2.final特点

黑马程序员_Java集合框架

- - - - - android培训.java培训.期待与您交流! - - - - - - 集合框架:用于存储数据的容器. 特点: 对象封装数据,对象多了也需要存储.集合用于存储对象. 对象的个数确定可以使用数组.如果不确定可以用集合.因为集合是可变长度的. 集合和数组的区别: 数组是固定长度的:集合可变长度的. 数组可以存储基本数据类型,也可以存储引用数据类型:集合只能存储引用数据类型. 数组存储的元素必须是同一个数据类型:集合存储的对象可以是不同数据类型. 数据结构:就是容器中存储数据的方

黑马程序员——Java集合基础知识之Collection

集合基础知识--Collection Java中集合框架由常用的Collection接口和Map接口组成,而Collection接口又有两个子接口,是List接口和Set接口,常用的集合框架由这三个类组成. List接口的功能方法 List的使用最为简单,创建集合,通过add方法添加元素,get方法获取元素,通过迭代器获取元素.List接口存放的数据无序的,添加速度快,但是查询速度慢,因为查询的时候必须遍历,每次都重头开始,效率较低.常用实现类有ArrayList,LinkedList. Lis

黑马程序员---Java集合框架

---------------------- Android开发.java培训.期待与您交流! ---------------------- Java集合框架 集合我们都知道是用来储存对象的容器,那之前的数组不也可以储存对象么,为什么要出现集合呢? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,然而集合类中提供很多方便操作对象存储的方法,要比数组更容易操作对象,而且集合的长度是可变的,然而数组长度确实固定不变的,这样不利于对对象的间隔储存.  数组和集

黑马程序员——Java集合工具类和泛型

Collections工具类和泛型 Collections和Collection Collections和Collection是不同的,Collections是工具类,用来操作集合的,而Collection是集合接口.Collections中有一系列的静态方法用来操作集合,但是不能更改集合内容.比如不能set()不能remove()元素,可以替换全部元素或者添加同一个元素. static List<String> list =Arrays .asList("one Two three

黑马程序员——Java集合基础知识之Map

Map概念 要同时存储两个元素Key和Value,他们之间有映射关系,每个键不能重复,每个键只能映射到一个值. 当数据之间存在映射关系的时候,考虑使用Map集合. Map常用方法 如果添加的键原来有值,后添加的值会覆盖前面的值,并返回之前的值.put会返回来先添加的值,后添加的值会覆盖原有的值. Map tm =new TreeMap(); tm.put (key, value);//MAP没有add tm.remove (key) ;//去除一个key和对应的value,若不存在key返回nu