Java集合框架01:Collection集合之List

什么是集合

用来存放对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能

集合和数组的区别:

  • 数组长度固定,集合长度不固定
  • 数组可以存储基本类型和引用类型,集合只能存储引用类型

Collection体系结构

Java集合框架01:Collection集合之List

Collection父接口

代表一组任意类型的对象,无序、无下标、不能重复

在开发过程中,很少会直接使用Collection接口,因为Collection接口只是一个存储数据的标准,并不能区分存储类型

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

public class Hello{
    public static void main(String[] args) {
        //Collection是接口无法实例化,只能声明对象,它的子类才可以实例化。可以使用父类接口声明引用变量,但不能使用其实现类独有的方法
        Collection collection = new ArrayList();

        //add()方法添加元素,如果元素是对象,那只是添加了其引用地址
        collection.add("java");
        collection.add("python");
        collection.add("c++");
        
        //因为集合只能存储引用类型,所以此处默认执行了自动装箱的操作
        collection.add(1);

        //remove()方法删除元素
        collection.remove("c++");

        //size()方法查看元素个数
        System.out.println(collection.size());

        //集合对象可以直接打印,内置了toString()方法
        System.out.println(collection);

        //两种遍历集合的方法
        //1.增强for循环(Collection接口类型没有下标,不能用普通for循环)
        //ArrayList对象的元素会被当成Object类型来处理,因此可以存储不同的数据类型
        for (Object i : collection){
            System.out.println(i);
        }

        //2.iterator()迭代器方法,返回值是Iterator接口类型
        Iterator it  = collection.iterator();
        //迭代器对象的hasNext()方法先判断集合还有没有元素
        while (it.hasNext()){
            //next()方法取出元素
            System.out.println(it.next());
            //如果需要删除元素,只能使用迭代器对象的it.remove()方法
            //it.remove();
        }

        //contains()方法判断元素是否存在
        System.out.println(collection.contains("c++"));

        //isEmpty()方法判断集合是否为空
        System.out.println(collection.isEmpty());
    }
}

List子接口

有序、有下标、元素可以重复

拥有Collection接口的所有方法,还有自己的方法,如可指定位置添加的add()方法、get()、listIterator()、subList()方法等

ArrayList实现类

数组结构实现,存储空间连续,查询快,增删慢

运行效率快,线程不安全

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Hello{
    public static void main(String[] args) {
        //List list = new ArrayList();也可以
        ArrayList list = new ArrayList();

        //add()方法可指定位置添加元素
        list.add("java");
        list.add(0, "python");
        list.add("c++");
        list.add(1);
        
        //subList()方法截取集合的子集
        System.out.println(list.subList(1, 3));

        //remove()方法可根据下标或内容删除元素
        list.remove(0);
        list.remove("c++");
        //注意,remove()方法中数字代表的是下标,若要删除的元素本身是数字,则需要转换一下类型
        list.remove((Object) 1);

        //三种遍历集合的方法
        //1.for循环或增强for循环
        for (int i = 0; i < list.size(); i++) {
            //get()方法根据下标获取元素
            System.out.println(list.get(i));
        }

        //2.iterator()迭代器方法

        //3.listIterator()列表迭代器方法,可以向前向后遍历、添加、删除、修改元素
        ListIterator li = list.listIterator();
        while (li.hasNext()){
            //next
            System.out.println(li.nextIndex() + ":" + li.next());
        }
        while (li.hasPrevious()){
            System.out.println(li.previousIndex() + ":" + li.previous());
        }

        //indexOf()方法获取元素的下标
        System.out.println(list.indexOf("java"));
    }
}

拓展:ArrayList源码分析

//ArrayList()
//集合默认是容量为10
private static final int DEFAULT_CAPACITY = 10;

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        //如果没有添加任何元素,容量为0;添加一个元素之后,容量变成10
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

//add()
private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    //每次扩容,容量增大1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

LinkedList实现类

双向链表结构实现,存储空间不连续,增删快,查询慢

拓展:LinkedList源码分析

void linkLast(E e) {
    final Node<E> l = last;
    final Node<E> newNode = new Node<>(l, e, null);
    last = newNode;
    if (l == null)
        first = newNode;
    else
        l.next = newNode;
    size++;
    modCount++;
}

private static class Node<E> {
    //item是实际数据
    E item;
    //next是下一个节点
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}
上一篇:2021-09-11


下一篇:Java高级编程基础——集合框架