Java--集合--ArrayList

Java--集合--ArrayList,第1张

Java--集合--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()

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

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 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 表示该属性不会被序列化 

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

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5672998.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-16
下一篇2022-12-17

发表评论

登录后才能评论

评论列表(0条)

    保存