Java学习Day12-集合容器(ArrayList、LinkedList)

集合容器

Array和ArrayList的区别是什么?

  • Array是数组,ArrayList是类
  • Array是定长的(需要手动扩容),ArrayList长度可变(使用过程中自动扩容)
  • ArrayList的底层是Array

数组(Array)有什么缺点

  • 再创建数组的时候,就需要定死长度,在运行过程中需要判断剩余长度,并动态扩容
  • 在中间插入的时候,需要将后面的元素进行后移
  • 在中间删除的时候,需要将后面的元素进行前移

数组的特点:有序的,不唯一的

数组的封装类 - 列表(ArrayList)

学习一个类的步骤:

1、构造方法(先研究如何构造对象)

        ArrayList()

        ArrayList(int)

2、成员变量(研究构造出来的对象中有什么)

        elementData        Object[ ]类型

        size                       int类型

3、成员方法(研究如何操作对象中的成员)

        add(int)        在数组尾部的第一个不为空的位置添加

        add(int,E)     在数组中的指定位置插入

        set(int,E)        修改数组指定位置

        remove(int)        根据索引号移除

        remove(Object)        根据指针移除,如果存在多个同样值,只会删除第一个

        get(int)                根据指定的索引号找到某个元素并返回

size是记录容器中数组不为null的个数,私有静态方法

size()方法是查看容器中数组不为null的个数

 补充上图:

我们不需要考虑数组的扩容问题

我们不需要遍历数组,找第一个不为NULL的位置(官方在原码中维护了一个size变量)

添加:

add()无参

add(index,)有参

删除:

remove(index)根据索引号进行删除

remove(Object)根据指针进行删除

修改:

set()

ArrayList类中的那个“E”到底是什么?

泛型 - 作者在编写的时候用 E 来表达未知的数据类型

        - 调用者在使用的时候,可以给出 E 的具体类型,也可以不给出

         - 如果给出E的具体类型,是在构造ArrayList对象的时候给出

        例如:E = String        E = Car

                  不给的话 E = Object

        给出E的具体数据类型的语法

        ArrayList<String>al1 = new ArrayList();

        ArrayList<Car>al1 = new ArrayList();

用泛型来实现类中用到的数据类型(可以是参数类型,可以是返回值类型,可以是任意变量的类型,可以是向下转型的类型)

用泛型的好处是被调用方可以帮调用方写向下转型的代码

双向链表 - LinkedList类(底层是Node类)

1、构造方法

2、成员变量

3、成员方法

        增:

        addFirst(E)        在头部添加

        addLast(E)        在尾部添加

        add(E)        在尾部追加

        add(int,E)        在指定位置插入

        链表在中间插入的速度要优于数组,只需要找到插入的位置的节点,创建新节点,然后修改指针即可

        数组在尾部插入比较快,但是在首部或者中间插入比较慢,因为需要后移

       速度对比:

        数组:遍历数组,指定位置后面的元素要后移

        链表:遍历链表,指定的位置插入

        删:

        

        removeFirst(E)删除头部

        removeLast(E)删除尾部

        remove(int)根据指定位置删除

        remove(Object)根据指定元素删除

         改:

        set(int,E)

        查:

        

        get(int)链表并没有索引的机制,底层通过遍历链表然后通过二分查找法找到指定位置的节点,并返回节点中的item

        从查询角度看数组的性能要优于链表

        中间插入和删除,链表优于数组

        查询和修改,数组要优于链表

        链表不需要扩容和转移,数组需要

LinkedList的内部类 - Node类(用于创建双向链表中的节点对象)

 

ArrayList和LinkedList的区别是什么?

1、底层数据结构的实现:ArrayList底层数据结构是动态数组,而LinkedList的底层数据结构是双向链表

2、随机访问(即读)效率:ArrayList比LinkedList在随机访问的时候效率要高,因为ArrayList底层是数组,可以通过索引号快速访问,LinkedList是通过二分查找遍历链表节点进行查找的

3、增加和删除效率:在非首尾的增加和删除操作,LinkedList要比ArrayList效率要高,因为ArrayList增删操作需要大量的前移或者后移,这个过程中涉及到大量的赋值操作比较耗费时间,LinkedList只需要修改节点对象的左右指针即可

4、内存空间占用:LinkedList比ArrayList更占内存,因为LinkedList的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素

5、综合来说,在需要频繁读取集合中的元素时,更推荐ArrayList,而在插入和删除操作较多时,更推荐使用LinkedList

遍历ArrayList和LinkedList的几种方式

1、普通for循环

2、增强型for循环

3、forEach循环

4、迭代器

import java.util.ArrayList;
import java.util.Iterator;

public class Demo04 {
    public static void main(String[] args) {
        ArrayList<String> al1 = new ArrayList();
        al1.add("张飞");
        al1.add("赵云");
        al1.add("马超");
        al1.add("关羽");
        al1.add("黄忠");
        System.out.println("*****遍历方式一:普通for循环*****");
        for (int i = 0; i< al1.size();i++){
            System.out.print(al1.get(i) + " ");

        }
        System.out.println("\n*****遍历方式二:增强型for循环*****");
        //冒号左边是一个临时变量String item 这个临时变量的数据类型与al1的泛型必须保持一致
        //每循环一次就会自动从al1中取出一个元素付给item
        //1、不需要写循环四要素
        //2、不需要手动执行al1.get(i)操作了
        for (String item : al1){
            System.out.print(item+" ");   //不需要执行al1.get(i)
        }
        System.out.println("\n*****遍历方式三:forEach*****");
        //用al1调用forEach函数
        //forEach函数的参数是一个箭头函数
        //箭头函数的语法为:(参数名) -> {}
        //al1.forEach   循环存在    在forEach函数里面    forEach会遍历al1   取出每个值后会回调你的箭头函数,并把值传给箭头函数的参数
        al1.forEach((item) -> {
            System.out.print(item + " ");
        });
        System.out.println("\n*****遍历方式四:迭代器*****");
        //调用iterator()方法,返回一个迭代器对象
        //使用iterator类声明一个迭代器指针,迭代器的泛型必须和al1的泛型保持一致
        Iterator<String> iterator = al1.iterator();
        //迭代器的hasNext()方法可以判断是否还有下一个元素
        while (iterator.hasNext()){
            //迭代器next()方法可以取出下一个元素
            String item = iterator.next();
            System.out.print(item + " ");
        }
    }
}

整理ArrayList和LinkedList的常用方法

ArrayList和Vector的区别(带一下CopyOnWriteArrayList)

ArrayList是线程不安全的,Vector是线程安全的。ArrayList中的所有方法都没有加同步锁,Vector中所有方法都加了synchronized同步锁。官方在JDK1.5版本中又推出了一个CopyOnWriteArrayList,使用了Lock锁实现线程安全,然后弃用Vector,因为Lock锁的性能比synchronized锁的性能好。

在并发编程中,如果多个线程共享一个ArrayList,那么必须考虑线程安全的问题,可以自己在代码中对ArrayList操作代码加锁,或者直接用线程安全的CopyOnWriteArrayList类,在不考虑线程安全的环境下,用ArrayList性能更好,因为加锁和开锁是很消耗性能的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值