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

什么是集合

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

任何放入集合的对象,都会转换为Object类型,因此集合可以放置任何对象

集合和数组的区别:

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

Collection体系结构

Collection父接口

代表一组任意类型的对象集合

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

add()、remove()、size()、toArray()、contains()、iterator()、clone()方法

import java.util.ArrayList;
import java.util.Arrays;
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);

        //toArray()方法将集合转换成数组
        System.out.println(Arrays.toString(collection.toArray()));

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

        //两种遍历集合的方法
        //1.增强for循环(Collection接口类型没有下标,不能用普通for循环)
        for (Object i : collection){  //集合元素都是Object类型
            System.out.println(i);
        }

        //2.iterator()迭代器方法,声明一个Iterator接口类型的引用变量
        Iterator it  = collection.iterator();
        //迭代器对象的hasNext()方法先判断集合还有没有元素
        while (it.hasNext()){
            //next()方法取出元素
            System.out.println(it.next());
            //此时如果需要删除元素,只能使用迭代器对象的remove()方法,并且必须要调用过next()方法
//            //it.remove();
        }
    }
}

拓展:正确遍历集合的同时删除元素

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

public class Hello{
    public static void main(String[] args) {
        ArrayList list = new ArrayList();

        //创建一个集合
        for (int i = 0; i < 10; i++) {  //[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
            list.add(i);
        }

        //clone()方法可以复制集合,复制后的结果是Object类型,需要强制转换(浅拷贝,和Object类相比不用实现Cloneable接口)
        ArrayList list1 = (ArrayList) list.clone();
        ArrayList list2 = (ArrayList) list.clone();

        //1.直接for循环遍历删除元素会出错,因为删除一个元素后,集合长度发生了改变(数组长度是不变的)
        for (int i = 8; i < list.size(); i++) {  //目的是删除8和9,但实际在删除8以后,集合长度缩短了,因此9会被漏掉
            list.remove(i);
        }
        System.out.println(list);  //[0, 1, 2, 3, 4, 5, 6, 7, 9]

        //2.在删除元素以后,手动将i减1,和数组的长度保持一致,就可以正确删除
        for (int i = 8; i < list1.size(); i++) {
            list1.remove(i);
            i--;
        }
        System.out.println(list1);  //[0, 1, 2, 3, 4, 5, 6, 7]

        //3.推荐使用Iterator()迭代器删除,不会受集合长度变化的影响
        Iterator it = list2.iterator();
        int index = 0;
        while (it.hasNext()){
            Object next = it.next();  //remove()方法只有在调用了next()方法后才可以使用
            
            if (index >= 8){  //迭代器没有下标,但是按顺序迭代的,所以可以将循环次数作为下标
                it.remove();
            }
            index++;
        }
        System.out.println(list2);  //[0, 1, 2, 3, 4, 5, 6, 7]
    }
}

List子接口

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

拥有Collection接口的所有方法,还有自己的方法

ArrayList实现类

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

运行效率快,线程不安全

add()、subList()、remove()、get()、indexOf()、set()、listIterator()方法

import java.util.ArrayList;
import java.util.Iterator;
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));  //[java, c++],该方法需要变量接收,不会对原集合产生影响
        System.out.println(list);  //[python, java, c++, 1]

        //remove()方法可根据数字下标(int类型)或内容删除元素,直接对原集合操作,若元素本身是数字(Object类型),需要表明类型才能删除
        list.remove(0);
        list.remove("c++");
        list.remove((Object) 1);
        System.out.println(list);  //[java]

        //get()方法根据下标获取元素
        System.out.println(list.get(0));

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

        //set()方法替换指定位置的元素
        list.set(0, "Java");

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

        //2.iterator()迭代器方法
        Iterator it = list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

        //3.listIterator()列表迭代器方法,创建一个ListIterator接口类型引用,可以向前后遍历
        ListIterator li = list.listIterator();
        while (li.hasNext()){
            //nextIndex()方法获取下标,next()方法获取元素
            System.out.println(li.nextIndex() + ":" + li.next());
        }

        while (li.hasPrevious()){
            System.out.println(li.previousIndex() + ":" + li.previous());
        }
    }
}

拓展: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实现类

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

方法和ArrayList基本一样,也有自己的方法

removeFirst()、removeLast()方法

import java.util.LinkedList;

public class Hello{
    public static void main(String[] args) {
        LinkedList list = new LinkedList();

        //add()方法可指定位置添加元素,是有序的
        list.add("java");
        list.add("c++");
        list.add("python");

        Object first = list.removeFirst();  //removeFirst()方法删除并返回第一个元素
        Object last = list.removeLast();  //removeLast()方法删除并返回最后一个元素

        System.out.println(first);  //java
        System.out.println(last);  //python
        System.out.println(list);  //[c++]
    }
}

拓展: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;
    }
}
posted @ 2021-09-10 15:50  振袖秋枫问红叶  阅读(76)  评论(0)    收藏  举报