Java--集合--ArrayList

本文详细介绍了Java集合框架中的单列集合(单对象)和双列集合(键值对),重点讲解了ArrayList、Vector(Vector是ArrayList的线程安全版本)和LinkedList的区别。涵盖了添加、删除、遍历、编译与运行类型等内容,以及ArrayList的内部实现机制。

1. 集合框架

单列集合(单个对象)

双列集合(键值对)

2.Collection接口和常用方法

实现子类ArrayList

List list = new ArrayList();

2.1 add

list.add(); //可存入任何类型的对象,直接存入数据或者布尔值会进行类型判别

list.add(10);  //相当于list.add(new Integer(10))

2.2 remove

list.remove()//

list.remove(index);  //指定元素下标删除

list.remove("object");  //指定对象删除

Q:怎么以删除指定对象方式删除整型元素?

2.3 contains()

//接受一个对象,查找元素是否存在,返回boolean

2.4 size()

//获取元素个数

2.5 isEmpty()

//判断是否为空

2.6 clear()

//清空

2.7 addAll()

//接受一个实现Colleticon的对象并将其加入当前对象

//合并两个ArrayList

3.Collection接口遍历元素方式

迭代器Iterator执行原理

//hasNext()判断是否有下一个元素

//next()将指针下移并返回下移后位置的元素

//System.out.println(iterator.next())

3.1 使用Collection实现的接口iterator遍历--while

Collection list = new ArrayList();
while(list.hasNext()) {
    Object obj = iterator.next();
    System.out.println(obj);
}

循环结束后,指针指向列表的最后一个元素

若要重新循环遍历,则要重置iterator

iterator = list.iterator();
//重置iterator,

3.2 使用Collection接口遍历对象--for循环增强

Collection list = new ArrayList();
        list.add(new Book("Alan", 12));
        list.add(new Book("Hulk", 21));
        Iterator iterator = list.iterator();
        for(Object book : list) {
            //book为循环对象
            System.out.println("book=" + Book);
        }
//也可以用来访问数组

int[] nums = {1,2,3};
for(Object i : nums){
    System.out.println(i);
}

底层仍然是迭代器

for循环的判断语句中,先调用Iterator

public Iterator<E> iterator() {
    return new Itr();
}

接着判断是否有下一个元素

public boolean hasNext() {
    return cursor != size;
}

最后调用next()方法

public E next() {
    checkForComodification();
    int i = cursor;
}

4. 编译类型和运行类型

编译时类型由声明该变量时使用的类型决定(比如可声明为类的父类),运行时类型由实际赋给该变量的对象决定

(参考C++的动态绑定)

与方法不同的是,对象的属性则不具备多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性。

5. List接口和常用方法

5.1 List接口特点:

5.1.1 List集合类中元素有序(添加顺序和取出顺序一致),且可重复

5.1.2 支持顺序索引(索引从0开始)

5.1.3 实现List接口的类有ArrayList,LinkedList,Vector,Stack,AbstractList等

5.2 List接口方法:

        List list = new ArrayList();
        List list_2 = new ArrayList();
        list_2.add("four");
        list_2.add("five");
        list.add("one");
        list.add("three");
        list.add(1,"two");
        list.add("one");
        //insert new object into the index you want
        list.addAll(1,list_2);
        //insert another Collection Object into the index you want
        System.out.println(list.get(1));
        //get object by index
        System.out.println(list.indexOf("one"));
        //return the index where the object is setted first time
        System.out.println(list.lastIndexOf("one"));
        //return the index where the object is setted last time
        System.out.println(list.remove(1));
        //remove object by index and return the object
        System.out.println(list);
        list.set(1, "ten");
        //replace the object by index with a new object
        System.out.println(list.subList(1,4));
        //get the subList by index
        //from fromIndex to toIndex(not involve toIndex)
  

6.List接口的三种实现类ArrayList,Vector,LinkedList的三种遍历方式

        System.out.println("\n--------in while-------\n");
        Iterator it = list.iterator();
        while(it.hasNext()) {
            System.out.println(it.next());
        }

        System.out.println("\n---------in for--------\n");
        for(Object o : list) {
            System.out.println(o);
        }

        System.out.println("\n-------in simple--------\n");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        //编译类型为List,运行类型ArrayList,Vector,LinkedList都适用

7. ArrayList

7.1 可以加入多个null

List list = new ArrayList();
list.add(null);

7.2 ArrayList是由数组来实现数据存储的

7.3 ArrayList基本等同于Vector,执行效率高,但是是线程不安全的。添加元素时没有synchronized互斥操作。

7.4 ArrayList底层机制和源码分析

ArrayList构造器:

 7.4.1 ArrayList中维护了一个Object类型的数组elementData(什么类型的数据都可以放)

 transient Object[] elementData; //transient 表示该属性不会被序列化(序列化详见JAVA--序列化) 

反序列化:从IO流中恢复对象

7.4.2 创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍

7.4.3 如果使用的是指定大小的构造器,则初始化elementData容量为指定大小,如果需要扩容,则直接扩容为elementData为1.5倍

Debug : ArrayList扩容

ArrayList list = new ArrayList();
for(int i = 1; i <= 10; i++) {
    list.add(i); //jump
}
public boolean add(E e) {
    ensureCapacityInternal(size + 1);  
    //size = 0 
    //jump
    elementData[size++] = e;
    //size是位置指针
    return true; 
}
private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); //minCapacity=1 
    //第一次扩容时候,DEFAULT_CAPACITY=10,minCapacity=1
    }
    
    ensureExplicitCapacity(minCapacity);
    //这里minCapacity = 10
    //jump
}
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;//扩容计数
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
        //jump
}

Tips:

transient Object[] elementData;

// java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    //初始elementData.length = 0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // ">>"位移操作符,变为之前的二分之一,即新的容量为之前的1.5倍
    if (newCapacity -minCapacity < 0)
        newCapacity = minCapacity;
    //如果扩容后的容量仍然小于所需容量,则新容量之间等于所需容量
    if(newCapacity - Max_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    //如果扩容后的容量大于ARRAY提供的最大容量,则
    elementData = Arrays.cptyOf(elementData, newCapacity);
    //将数据移入扩容后的ArrayList
    //junp
    //拷贝之前的数据,并把没有值的位置置为null

}

7.4.4 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍

ArrayList list = new ArrayList(6);
for (int i = 1; i <= 10; i++) {
    list.add(i);
}
//当循环至i=7时,list扩容为9

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值