Java集合01:Collection集合,List子集合,ArrayList实现类和LinkedList实现类

集合

  1. 什么是集合

对象的容器,实现了对象的常用操作。类似数组的功能

  1. 集合与数组的区别
  • 数组的长度固定,集合的长度不固定
  • 数组可以存储基本类型和引用类型,而集合只能存储引用类型
  1. 集合的存储位置

集合存放在 java.util.* 包下

Collection集合

  1. Collection体系集合
    在这里插入图片描述
  2. 什么是Collection接口

Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection

  1. Collection接口的方法
用法解释
boolean add(E e)确保此 collection 包含指定的元素(可选操作)。
boolean addAll(Collection<? extends E> c)将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
void clear()移除此 collection 中的所有元素(可选操作)。
boolean contains(Object o)如果此 collection 包含指定的元素,则返回 true。
boolean containsAll(Collection<?> c)如果此 collection 包含指定 collection 中的所有元素,则返回 true。
boolean equals(Object o)比较此 collection 与指定对象是否相等。
int hashCode()返回此 collection 的哈希码值。
boolean isEmpty()如果此 collection 不包含元素,则返回 true。
Iterator iterator()返回在此 collection 的元素上进行迭代的迭代器。
boolean remove(Object o)从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
boolean removeAll(Collection<?> c)移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
boolean retainAll(Collection<?> c)仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
int size()返回此 collection 中的元素数。
Object[ ] toArray()返回包含此 collection 中所有元素的数组。
T[ ] toArray(T[ ] a)返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
  1. Collection实例
public class Demo1 {
    public static void main(String[] args) {
        Collection collection = new ArrayList();
        //增加元素
        collection.add("111");
        collection.add("222");
        collection.add("aaa");
        System.out.println("元素个数"+collection.size());
        System.out.println(collection);
        System.out.println("=========================================");
        //删除元素
        collection.remove("111");
        System.out.println("元素个数"+collection.size());
        System.out.println(collection);
        //collection.clear();//删除所有元素
        System.out.println("=========================================");
        //遍历元素
           //1.使用foreaech 增强for循环
        for (Object object:collection
           ) {
         System.out.println(object);
        }
           //2.使用迭代器(迭代器是专门用来遍历集合的一种方式)
           //迭代器具有的三个方法
        //hasNext();有没有下一个元素
        //next();获取下一个元素
        //remove();删除当前元素
        Iterator iterator=collection.iterator();
        while (iterator.hasNext()) {
            Object ob = iterator.next();
            System.out.println(ob);
       }
        //我们知道集合中是Stirng类型就可以直接强制转换
            Iterator iterator2=collection.iterator();
            while (iterator2.hasNext()){
                String s=(String) iterator2.next();
                System.out.println(s);
                //collection.remove(s);
                System.out.println(collection);
              iterator2.remove();//删除当前元素,指针是不动的
        }
        System.out.println("元素个数"+collection.size());
        System.out.println(collection);
        System.out.println("=========================================");
          //判断
          //判断是否有这个元素,有返回ture
        System.out.println(collection.contains("222"));
        //判断集合是否为空,为空返回ture
        System.out.println(collection.isEmpty());

    }
}

List子接口

  1. List接口特点
  • 此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
  • 有序,有下标,元素可重复
  1. List接口的方法
用法解释
boolean add(E e)向列表的尾部添加指定的元素(可选操作)。
void add(int index, E element)在列表的指定位置插入指定元素(可选操作)。
boolean addAll(Collection<? extends E> c)添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。
boolean addAll(int index, Collection<? extends E> c)将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
void clear()从列表中移除所有元素(可选操作)。
boolean contains(Object o)如果列表包含指定的元素,则返回 true。
boolean containsAll(Collection<?> c)如果列表包含指定 collection 的所有元素,则返回 true。
boolean equals(Object o)比较指定的对象与列表是否相等。
E get(int index)返回列表中指定位置的元素。
int hashCode()返回列表的哈希码值。
int indexOf(Object o)返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
boolean isEmpty()如果列表不包含元素,则返回 true。
Iterator iterator()返回按适当顺序在列表的元素上进行迭代的迭代器。
int lastIndexOf(Object o)返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
ListIterator listIterator()返回此列表元素的列表迭代器(按适当顺序)。
ListIterator listIterator(int index)返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
E remove(int index)移除列表中指定位置的元素(可选操作)。
boolean remove(Object o)从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。
boolean removeAll(Collection<?> c)从列表中移除指定 collection 中包含的其所有元素(可选操作)。
boolean retainAll(Collection<?> c)仅在列表中保留指定 collection 中所包含的元素(可选操作)。
E set(int index, E element)用指定元素替换列表中指定位置的元素(可选操作)。
int size()返回列表中的元素数。
List subList(int fromIndex, int toIndex)返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
Object[] toArray()返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)。
T[] toArray(T[] a)返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。
  1. ListIterator具有的方法
用法解释
void add(E e)将指定的元素插入列表(可选操作)。
boolean hasNext()以正向遍历列表时,如果列表迭代器有多个元素,则返回 true(换句话说,如果 next 返回一个元素而不是抛出异常,则返回 true)。
boolean hasPrevious()如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
E next()返回列表中的下一个元素。
int nextIndex()返回对 next 的后续调用所返回元素的索引。
E previous()返回列表中的前一个元素。
int previousIndex()返回对 previous 的后续调用所返回元素的索引。
void remove()从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
void set(E e)用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。
  1. List接口实例
 public static void main(String[] args) {
        List list = new ArrayList();
        //1.添加元素
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        list.add("ddd");
        System.out.println("元素个数"+list.size());
        System.out.println(list.toString());
        //2.删除元素
        list.remove("aaa");
        //list可以通过下标删除
        list.remove(0);
        System.out.println("元素个数"+list.size());
        System.out.println(list.toString());
        //list.clear();
        //3.遍历
        //3.1使用for循环
        for (int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        //3.2使用增强for
        for (Object object:list
             ) {
            System.out.println(object);
        }
        //3.3使用迭代器Iterator
        Iterator iterator =list.iterator();
        while (iterator.hasNext()){
            System.out.println( iterator.next());
        }

        //3.4使用ListIterator
        ListIterator listIterator = list.listIterator();
        //ListIterator从前往后输出
        while (listIterator.hasNext()){
           System.out.println(listIterator.nextIndex()+":"+listIterator.next());
        }
        //ListIterator从后往前输出,这个如果指针指向的是第一个元素就没有用了
        //hasPrevious判断的是有没有前一个元素,这里之所以能直接输出是因为前面用了hasNext,已经将指针指向了最后一位
        while (listIterator.hasPrevious()){
            System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
        }
        //4.判断
        System.out.println(list.contains("ccc"));
        System.out.println(list.isEmpty());
        //5.获取位置下标
        System.out.println(list.indexOf("ddd"));
    }
  1. List接口实现类

ArrayList:

  • 数组结构实现,查询快,增删慢
  • JDK1.2版本,运行效率快,线程不安全
    Vector:(了解就行)
  • 数组结构实现,查询快,增删慢
  • JDK1.0版本,运行效率慢,线程安全
    LinkedList:
  • 链表结构实现,查询慢,增删快

ArrayList

  1. ArrayList实现类的特点

数组,查找遍历速度快,增删慢

  1. ArrayList类的方法
用法解释
boolean add(E e)将指定的元素添加到此列表的尾部。
void add(int index, E element)将指定的元素插入此列表中的指定位置。
boolean addAll(Collection<? extends E> c)按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
boolean addAll(int index, Collection<? extends E> c)从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
void clear()移除此列表中的所有元素。
Object clone()返回此 ArrayList 实例的浅表副本。
boolean contains(Object o)如果此列表中包含指定的元素,则返回 true。
void ensureCapacity(int minCapacity)如有必要,增加此 ArrayList 实例的容量,以确保它至少能够容纳最小容量参数所指定的元素数。
E get(int index)返回此列表中指定位置上的元素。
int indexOf(Object o)返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1。
boolean isEmpty()如果此列表中没有元素,则返回 true
int lastIndexOf(Object o)返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
E remove(int index) 移除此列表中指定位置上的元素。
boolean remove(Object o)移除此列表中首次出现的指定元素(如果存在)。
protected void removeRange(int fromIndex, int toIndex)移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。
E set(int index, E element)用指定的元素替代此列表中指定位置上的元素。
int size()返回此列表中的元素数。
Object[] toArray()按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组。
T[] toArray(T[] a)按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。
void trimToSize()将此 ArrayList 实例的容量调整为列表的当前大小。
  1. ArrayListt的使用
 public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        //添加元素
        Student s1=new Student("张三",1);
        Student s2=new Student("李四",2);
        Student s3=new Student("王五",3);
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        System.out.println("元素个数"+arrayList.size());
        System.out.println(arrayList.toString());
        //删除元素
        arrayList.remove(new Student("张三",1));//调用equals方法比较,
                      // 因为Object中的equals方法是比较前后两个的地址是否相同,
                     // 所有我们在子类Student中重写父类Object的equals方法
                    //1.判断是否为同一个对象2.判断是否为空3.判断是否为Student类型
                   //4.如果是Student类型,自行添加判断条件(这里是name和age必须一样)

        System.out.println("元素个数"+arrayList.size());
        System.out.println(arrayList.toString());

        //3.遍历
           //3.1使用迭代器Iterator
        Iterator iterator =arrayList.iterator();

        while (iterator.hasNext()){
            System.out.println( iterator.next());
        }

        //3.2使用ListIterator
        ListIterator listIterator = arrayList.listIterator();
            //ListIterator从前往后输出
        while (listIterator.hasNext()){
            System.out.println(listIterator.nextIndex()+":"+listIterator.next());
        }
           //ListIterator从后往前输出,这个如果指针指向的是第一个元素就没有用了
           //hasPrevious判断的是有没有前一个元素,这里之所以能直接输出是因为前面用了hasNext,已经将指针指向了最后一位
        while (listIterator.hasPrevious()){
            System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
        }

        //4.判断

        System.out.println(arrayList.contains(s1));
        System.out.println(arrayList.contains(new Student("王五",3)));
        System.out.println(arrayList.isEmpty());


        //5.获取位置下标
        System.out.println(arrayList.indexOf(s2));
    }

Student类中重写的equals方法

 @Override
    public boolean equals(Object o) {
     //this所指的是已经在集合中的对象
     //因为我传的是new Student("张三",1)所以Object类0指向的是Student子类的对象
        if (this == o) return true;
        if (o == null ) return false;
        //因为Object类0指向的是子类Student的对象,所以if为真
        if(o instanceof Student) {
        
            Student student = (Student) o;// Student student = new Student();
           if (this.age == student.age && this.name.equals(student.name))
           {
               return true;
           }
        }

        return false;
    }

  1. ArrayList源码分析

几个常见的常量:

  1. 默认容量为10: DEFAULT_CAPACITY=10(这里如果我们没有向集合中添加任何元素则容量大小为0)
  2. 存放元素的数组 : elementData
  3. 实际的元素的个数: size

简单分析ArrayList中的add方法
总结:扩容就是当我添加第11个元素时,数组大小由10变为15,所以每次到数组大小峰值时就扩容为原来的1.5倍

public boolean add(E e) {
         1.我们进入ensureCapacityInternal,当我添加第一个元素时size+11
         18.当我添加第11个元素时就要进行扩容了,此时size+111,再进入ensureCapacityInternal
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

             4.这里elementData数组为null,minCapacity为1
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
             5.这里DEFAULTCAPACITY_EMPTY_ELEMENTDATA也为null
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
             6.这里比较调用Math的max方法比较大小,DEFAULT_CAPACITY为10,minCapacity为1
        所以返回10
    return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
             20.返回11
    return minCapacity;
    }
    19.minCapacity为11
   2.当我添加第一个元素时size+11,所以minCapacity为1
    private void ensureCapacityInternal(int minCapacity) {
        3.这里elementData数组为null,minCapacity为1,我们先进入calculateCapacity
       7.发现返回值为10,我们再进入ensureExplicitCapacity
        21.这里返回11,我们再进入ensureExplicitCapacity
  ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }
   8.minCapacity为10
    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        9.这里minCapacity 为10,elementData.length为0
        22.minCapacity为11,elementData.length为10,因为里面有10个元素
    if (minCapacity - elementData.length > 0)
        23.进入grow方法
        10.所以我们进入grow方法
   grow(minCapacity);
    }
11此时进入grow方法minCapacity为10
private void grow(int minCapacity) {
        // overflow-conscious code
             24.这个elementData.length为10,所以oldCapacity为10
             12.这个elementData.length为0,所以oldCapacity为0
     int oldCapacity = elementData.length;
        25.oldCapacity + (oldCapacity >> 1)10+10右移一位(右移一位相当于除以2)结果为15,所以newCapacity 为15
        13.oldCapacity + (oldCapacity >> 1)0+0右移一位结果还是0,所以newCapacity 为0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
        26.newCapacity - minCapacity为15-10,所以大于0
        14.newCapacity - minCapacity为0-10,所以小于0
    if (newCapacity - minCapacity < 0)
        15.所以newCapacity =10
     newCapacity = minCapacity;
         16.( MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;)所以MAX_ARRAY_SIZE很大,if基本不成立 
    if (newCapacity - MAX_ARRAY_SIZE > 0)
    newCapacity = hugeCapacity(minCapacity);
        // minCapacity is usually close to size, so this is a win:
        17.使用数组的copyOf,创建了一个大小为10的数组elementData
        27.此时elementData为10,newCapacity为15,所以创建了大小为15的数组elementData 
    elementData = Arrays.copyOf(elementData, newCapacity);
    }

LinkedList

  1. LinkedList的特点:
  • 双向链表结构实现,查询慢,增删快
  1. LinkedList类的方法
用法解释
boolean add(E e)将指定元素添加到此列表的结尾
void add(int index, E element)在此列表中指定的位置插入指定的元素。
boolean addAll(Collection<? extends E> c)添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序。
boolean addAll(int index, Collection<? extends E> c)将指定 collection 中的所有元素从指定位置开始插入此列表。
void addFirst(E e)将指定元素插入此列表的开头。
void addLast(E e)将指定元素添加到此列表的结尾。
void clear()从此列表中移除所有元素。
Object clone()返回此 LinkedList 的浅表副本。
boolean contains(Object o)如果此列表包含指定元素,则返回 true。
Iterator descendingIterator()返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。
E element()获取但不移除此列表的头(第一个元素)。
E get(int index)返回此列表中指定位置处的元素。
E getFirst()返回此列表的第一个元素。
E getLast()返回此列表的最后一个元素。
int indexOf(Object o)返回此列表中首次出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。
int lastIndexOf(Object o)返回此列表中最后出现的指定元素的索引,如果此列表中不包含该元素,则返回 -1。
ListIterator listIterator(int index)返回此列表中的元素的列表迭代器(按适当顺序),从列表中指定位置开始。
boolean offer(E e)将指定元素添加到此列表的末尾(最后一个元素)。
boolean offerFirst(E e)在此列表的开头插入指定的元素。
boolean offerLast(E e)在此列表末尾插入指定的元素。
E peek()获取但不移除此列表的头(第一个元素)。
E peekFirst()获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
E peekLast()获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
E poll()获取并移除此列表的头(第一个元素)
E pollFirst()获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
E pollLast()获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
E pop()从此列表所表示的堆栈处弹出一个元素。
void push(E e)将元素推入此列表所表示的堆栈。
E remove()获取并移除此列表的头(第一个元素)。
E remove(int index)移除此列表中指定位置处的元素。
boolean remove(Object o)从此列表中移除首次出现的指定元素(如果存在)。
E removeFirst()移除并返回此列表的第一个元素。
boolean removeFirstOccurrence(Object o)从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。
E removeLast()移除并返回此列表的最后一个元素。
boolean removeLastOccurrence(Object o)从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。
E set(int index, E element)将此列表中指定位置的元素替换为指定的元素。
int size()返回此列表的元素数。
Object[] toArray()返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组。
T[] toArray(T[] a)返回以适当顺序(从第一个元素到最后一个元素)包含此列表中所有元素的数组;返回数组的运行时类型为指定数组的类型。
  1. LinkedList的使用
public static void main(String[] args) {
         //添加元素
        LinkedList linkedList = new LinkedList();
        Student s1 =new Student("aaa",15);
        Student s2 =new Student("bbb",16);
        Student s3 =new Student("ccc",17);
        Student s4 =new Student("ccc",17);
        linkedList.add(s1);
        linkedList.add(s2);
        linkedList.add(s3);
        linkedList.add(s4);
        System.out.println("元素个数"+linkedList.size());
        System.out.println(linkedList.toString());
        //删除元素
        linkedList.remove(s3);
        System.out.println("删除之后"+linkedList.size());
        System.out.println(linkedList.toString());
        //遍历
          //3.1 使用迭代器遍历
          Iterator iterator = linkedList.iterator();
          while(iterator.hasNext())
          {
              Object o=iterator.next();
              System.out.println(o);
          }
        //3.2使用ListIterator
        ListIterator listIterator = linkedList.listIterator();
          while(listIterator.hasNext()){
              Object o2=listIterator.next();
              System.out.println(listIterator.nextIndex()+":"+o2);
          }
        while (listIterator.hasPrevious()){
            System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
        }
        //判断
        System.out.println(linkedList.contains(s2));
        System.out.println(linkedList.isEmpty());
        //获取下标
        System.out.println(linkedList.indexOf(s1));
    }
  1. LinkedList源码分析

三个属性
transient int size = 0;大小
transient Node first;头节点
transient Node last;尾节点

add源码分析

1.进入add方法
  public boolean add(E e) {
2.进入linklast方法  
        linkLast(e);
        return true;
    }
 void linkLast(E e) {
 3.进入Node方法
 5.l指向last,l和last都为空
 11.当我们添加第二个节点,第7.中l指向的是第一个节点,所以l指向第一个节点
        final Node<E> l = last;
 6.创建一个newNode节点,l指向prev为空,元素e,next为null 
 12.创建第二个节点,l传给prev,l指向第一个节点,就是prev指向l,所以第二个节点指向第一个节点      
        final Node<E> newNode = new Node<>(l, e, null);
 7.last指向newNode   
 13.last指向第二个节点    
        last = newNode;
 8.l指向last,last为空,l为空    
 14.此时l指向的是第一个节点,有元素e不为空   
        if (l == null)
 9.first指向第一个节点       
            first = newNode;
        else
 15.l的下一个指向第二个节点,所以就是第一个节点指向第二个节点       
            l.next = newNode;
 10.  size+1          
        size++;
        modCount++;
    }
  private static class Node<E> {
        E item; //元素
        Node<E> next; //下一个
        Node<E> prev;  //前一个
     4.Node方法传参第一个是prev,第二个是element,第三个是next
        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

在这里插入图片描述

ArrayList和LinkedList的区别

ArrayList:必须开辟连续的空间,查询快,增删慢。
LinkedList:无需开辟连续空间,双向链表结构,查询慢,增删快。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值