java语言基础--集合学习,ArrayList和Linkedlist

Collection<E>接口

  这个接口是集合框架最顶级的接口,该接口扩展了Iterable接口,这意味着所有的集合类fore-each风格进行遍历。

ArrayList 与 Linkedlist

区别:

  ArrayList是实现了基于动态数组,LinkedList基于链表。对于随机访问get和set,ArrayList性能要优于LinkedList,因为LinkedList要移动指针。对于删除和新增LinkedList性能要优于ArrayList,因为ArrayList要移动数据。

ArrayList的扩容方式,扩容时机

  当集合中的元素超出容量,便会进行扩容操作。扩容操作也是ArrayList 的一个性能消耗比较大的地方,所以若我们可以提前预知数据的规模,应该通过public ArrayList(int initialCapacity) {}构造方法,指定集合的大小,去构建ArrayList实例,以减少扩容次数,提高效率

ArrayList的成员属性

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
    private static final long serialVersionUID = 8683452581122892189L;
    //默认初始容量
    private static final int DEFAULT_CAPACITY = 10;
    //默认构造函数的空数组
    private static final Object[] EMPTY_ELEMENTDATA = {};
    //瞬态(在采用Java默认的序列化机制的时候,被该关键字修饰的属性不会被序列化)的数组,真正存放元素的数组
    transient Object[] elementData; // non-private to simplify nested class access
    //elementData存放元素的数量,这里和容量不一样
    private int size;
}

ArrayList的构造方法

    public ArrayList(int initialCapacity) {
        super();//即父类protected AbstractList() {}
        if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity);
        this.elementData = new Object[initialCapacity];//创建一个容量为initialCapacity的空的(但是size==0)对象数组
    }

    public ArrayList() {
        super();
        this.elementData = EMPTY_ELEMENTDATA;//将空数组赋值给elementData
    }

    public ArrayList(Collection<? extends E> c) {
        //调用Collection.toArray()方法得到一个对象数组,并赋值给elementData
        elementData = c.toArray();
        //设置size的值
        size = elementData.length;
        //c.toArray()如果没有返回Object[]时,利用Arrays.copyOf 来复制集合c中的元素到elementData数组中
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    }

add方法

    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;//将数组元素追加到末尾,并修改size
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {
        //根据EMPTY_ELEMENTDATA  判断数组是否是用默认构造函数初始化的,(这里不考虑ArrayList(Collection<? extends E> c)这种情况是因为,minCapacity是肯定大于c的size的)
        if (elementData == EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;///如果确定要扩容,会修改modCount 

        // 如果传入的数大于数组原容量 则开始扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

    private void grow(int minCapacity) {
        //
        int oldCapacity = elementData.length;
        //扩容为原来的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        //取1.5倍的容量和传入的扩容系数的最大值
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)//这里的 MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
            newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    //最大返回 Integer.MAX_VALUE
    private static int hugeCapacity(int minCapacity) {
        // overflow
        if (minCapacity < 0) throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;
    }

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

    public void add(int index, E element) {
        rangeCheckForAdd(index);//范围检查

        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //将index开始的数据 向后移动一位
        System.arraycopy(elementData, index, elementData, index + 1,size - index);
        elementData[index] = element;
        size++;
    }

    private void rangeCheckForAdd(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

addAl方法

    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        //扩容准备
        ensureCapacityInternal(size + numNew);
        // 复制数组 ,并载入数据
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

查询

    public E get(int index) {
        rangeCheck(index);//范围检查

        return elementData(index);//下标获取数据
    }    

    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }

Linkedlist

    transient int size = 0;//集合元素数量

    transient Node<E> first; //头部节点

    transient Node<E> last;//尾部节点

构造方法

   public LinkedList() {}

    public LinkedList(Collection<? extends E> c) {
        this();
        addAll(c);//将集合c所有元素插入链表中
    }

内部类 Node

  //双向链表
  private static class Node<E> {
        E item;//元素值
        Node<E> next;//前节点引用
        Node<E> prev; //后节点引用

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

add方法

    //尾部插入新节点
    public boolean add(E e) {
        linkLast(e);
        return true;
    }

    void linkLast(E e) {
        final Node<E> l = last;//记录原来的尾部节点
        final Node<E> newNode = new Node<>(l, e, null);//以原尾部节点为前节点生成新节点
        last = newNode;//将当期节点设置为尾部节点
        if (l == null)//如果原尾部节点为null  则将当前节点设置为链表的首节点
            first = newNode;
        else//否则将当前节点设置为原尾部节点的后节点
            l.next = newNode;
        size++;
        modCount++;
    }

其他例子就不看了,总得来说 LinkedList  修改数据时,只需要设置新节点和关联前后节点关系即可,不向ArrayList那样,增加一个数据。后面的数据都要后移。因此LinkedList 对数据操作效率高。

原文地址:https://www.cnblogs.com/tjqBlog/p/9822307.html

时间: 2024-07-29 15:13:12

java语言基础--集合学习,ArrayList和Linkedlist的相关文章

C#语言基础——集合(ArrayList集合)

集合及特殊集合 集合的基本信息: System.Collections 命名空间包含接口和类,这些接口和类定义各种对象(如列表.队列.位数组.哈希表和字典)的集合.System.Collections.Generic 命名空间包含定义泛型集合的接口和类,泛型集合允许用户创建强类型集合,它能提供比非泛型强类型集合更好的类型安全性和性能.ystem.Collections.Specialized 命名空间包含专用的和强类型的集合,例如,链接的列表词典.位向量以及只包含字符串的集合. 常用的集合为Ar

java语言基础,学习笔记

001源代码编辑器输出字节码文件jvmeclipse中新建class文件,以及遇到基本错误的修改 public class A{ public static void main(String[] args){ System.out.printf("welcome to beijing lily") }}public ststic修饰符void返回类型为空main方法名()参数String字符型[]数组args参数值 //可修改 002 用记事本编写了java源程序并运行jdk下载及环境

No.1 java语言基础_学习笔记

import java.util.Scanner; public class HelloWorld { static final double PI=3.14; static int x=125; /** * 文档注释,程序名称:HelloWorld * 开发时间:2016-03-07 * 作者:嘿嘿 * */ public static void main(String[] args) { // TODO Auto-generated method stub System.out.printl

简单的入门Android开发和Java语言基础[图]

简单的入门Android开发和Java语言基础[图]前言:去年年底到今年年初,我做过简单的智能家居,也实现过一些简单的直连和远程的智能家居.于是就将最简单的通信发布出来:智能家居简单实现-使用ESP8266简单实现和APP通讯由于这方面的资料少之又少,所以阅读量飙升的很快.也有很多人加了好友问我问题.通过问题我发现,很多都是学硬件的.或是做智能家居方面的学生,基本都不会 Android 开发的.问也有很多问我怎么学 Android 开发的.很多的人认知还是停留在学习这种软件开发技术需要去培训机构

Java学习总结(二)----Java语言基础

1.     Java语言基础 2.1 关键字 定义:被java语言赋予特殊含义的单词 特点:关键字中的字母都为小写 用于定义数据类型的关键字 class,interface,byte,short,int, long ,float,double,char,boolean,void 用于定义数据类型值的关键字 true,false,null 用于定义流程控制的关键字 If,else,switch,case,default, while,do,for,break,continue,return 用于

非专业码农 JAVA学习笔记 2 java语言基础

java语言基础 (一)程序构成 略 (二)数据类型变量和常量 1.数据类型(与c#差不多) 布尔bool 8位 字节byte 8   -128-127 字符char 16 短整型Short 16 Int 32 Long 64 Float 32 Double 64 2.标识符-变量常量方法对象和类的名字标记 字母数字 还有两个特殊符号_ 和$ 字母下划线或者美元符号开头 3.常量 4.变量 (三)表达式 1.赋值和强制类型转换 Tostring()弱转换 类型=(类型)变量:a=(int)b;a

day05&lt;Java语言基础--数组&gt;

Java语言基础(数组概述和定义格式说明) Java语言基础(数组的初始化动态初始化) Java语言基础(Java中的内存分配以及栈和堆的区别) Java语言基础(数组的内存图解1一个数组) Java语言基础(数组的内存图解2二个数组) Java语言基础(数组的内存图解3三个引用两个数组) Java语言基础(数组的初始化静态初始化及内存图) Java语言基础(数组操作的两个常见小问题越界和空指针 Java语言基础(数组的操作1遍历) Java语言基础(数组的操作2获取最值) Java语言基础(数

2018.6.13 Java语言基础复习总结

Java语言基础与面向对象编程实践 第一章 初识Java 1.1机器语言 机器语言是指一台计算机全部的指令集合.机器语言室友0和1组成的二进制数,是一串串由0和1组成的指令序列,可将这些指令序列交给计算机执行. 1.2汇编语言 负责把汇编语言翻译成二进制的机器语言,这种翻译程序就是汇编程序. 1.3高级语言 1954年第一个完全脱离机器硬件的高级语言FORTRAN诞生 1.3.1C语言 是一种计算机程序设计语言,它既有高级语言的特点,又具有汇编语言的特点. 1.3.2 C++语言 是具有面向对象

Java图示(第二章 Java语言基础)

Java图示(第二章 Java语言基础) 三个基本部分:一个包声明(package语句).任意数量的引入(import语句).类和接口声明(class和interface语句) 1.包声明—package语句 1)包是类和接口的集合,即类库 2)用类库管理类,方便管理 3)Java类都在类库中 4)只有一条包声明,且为第一条 2.引入语句—import语句 1)import语句在包语句后,所有类或接口前 2)两种形式 (1)import 包名.类名: (2)import 包名*://编译器会识别