java集合之List接口及实现类

一、List子接口

  • 有序、有下标、可重复(可用for循环进行遍历)

  • 方法:

    • add(int index,Object o):在index位置插入对象o

    • addAll(int index,COllection c):将一个集合中的元素添加到此集合中的index位置

    • get(int index):返回集合中指定位置的元素

    • subList(int fromIndex,int toIndex):返回fromIndex和toIndex之间的集合元素

    • ...

      public class ListDemo {
          /**
           * List:有序、有下标、可重复
           * @param args
           */
          public static void main(String[] args) {
              List list=new ArrayList();
              List list1=new ArrayList();
              list1.add("苹果13promax");
              list1.add("小米10");
              //增加元素
              list.add("苹果13promax");
              list.add("小米10");
              list.add(0,"红米K30S");//通过下标来插入
              list.add(0,"红米K30");
              list.add(0,"红米K40");
              System.out.println(list.toString());
              //删除元素
              list.remove("小米10");
              list.remove(1);
              System.out.println(list.toString());
              //遍历
              System.out.println("-----------------for------------------");
              //1.for
              for (int i = 0; i < list.size(); i++) {
                  System.out.println(list.get(i));
              }
              System.out.println("-----------------foreach------------------");
              //2.foreach
              for (Object o : list) {
                  System.out.println(o);
              }
              System.out.println("-----------------iterator------------------");
              //3.迭代器iterator
              Iterator iterator = list.iterator();
              while(iterator.hasNext()){
                  System.out.println(iterator.next());
              }
              System.out.println("-----------------ListIterator()------------------");
              //4.迭代器ListIterator
              ListIterator listIterator = list.listIterator();
              while (listIterator.hasNext()){
                  listIterator.next();
              }//此时游标已经到了最后一个对象的后面,因此可用下面的方式输出
              while (listIterator.hasPrevious()){
                  System.out.println(listIterator.previous());
              }
              System.out.println("-----------------ListIterator(index)------------------");
              ListIterator listIterator1 = list.listIterator(1);//创建一个从1索引位置开始的List迭代器
              while (listIterator1.hasNext()){
                  System.out.println(listIterator1.next());
              }
              //判断
              System.out.println(list.contains("苹果13promax"));//true
              System.out.println(list.contains("苹果13promax "));//false
              System.out.println(list.isEmpty());
          }
      }
      
      //下面是第二个程序示例
      public class ListDemo02 {
          public static void main(String[] args) {
              List list=new ArrayList();
              list.add(20);//此处有自动装箱操作
              list.add(40);
              list.add(50);
              list.add(60);
              //list.remove("40");//无法删除
              //list.remove((Object)20);//需要先状装箱才能进行删除
              //list.remove((Integer)40);
              System.out.println(list);
              //subList方法:截取List(包含头,不包含尾)
              List list2 = list.subList(1, 4);
              System.out.println(list2);//[40, 50, 60]
          }
      }
      
  • list实现类

    • ArrayList:

      • 数组结构实现,查询快、增删慢(增加和删除要改变元素顺序)
      • JDK1.2版本,运行效率快、线程不安全
    • Vector(一般不用了):

      • 数组结构实现,查询快、增删慢
      • JDK1.0,运行效率慢、线程安全
    • LinkedList:

      • 链表结构实现,查询慢,增删快

      • 链表结构是通过一个个节点连接,首先有个头,头指向第二个节点,依次往下,因此在查询时,就比较慢,而删除的话只需要改变对下个结点的指向,因此比较快

二、ArrayList

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;
public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList arrayList=new ArrayList();
        Student s1=new Student("韩邦胜",20);
        Student s2=new Student("宋平",20);
        Student s3=new Student("韩平",20);
        //新增
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        System.out.println(arrayList.size());
        System.out.println(arrayList);
        //删除
        arrayList.remove(new Student("韩平",20));//要使用这种方式删除,需要重写Student的equals方法
        System.out.println(arrayList.size());
        System.out.println(arrayList);
        //遍历
        System.out.println("——————————迭代器——————————");
        Iterator it = arrayList.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        System.out.println("——————————列表迭代器——————————");
        ListIterator lit = arrayList.listIterator();
        while(lit.hasNext()){
            System.out.println(lit.next());
        }
        System.out.println("——————————列表迭代器逆序——————————");
        while(lit.hasPrevious()){
            System.out.println(lit.previous());
        }
        //包含
        System.out.println(arrayList.contains(new Student("宋平",20)));
        System.out.println(arrayList.isEmpty());
        //查找
        System.out.println(arrayList.indexOf(new Student("宋平",20)));
    }
}

//以下为Student类:
public class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        //1判断是不是同一个对象
        if (o==this){
            return true;
        }
        //2判断是不是null
        if (o==null){
            return false;
        }
        //3判断是不是Student类型
        if (o instanceof Student){
            //4判断属性值是否相等
            if (((Student) o).getName()==this.name&&((Student) o).getAge()==this.age){
                return true;
            }
        }
        //5否则返回false
        return false;
    }
}
  • ArrayList源码分析

    • DEFAULT_CAPACITY = 10 默认容量为10

    • size 数组大小

public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}//ArrayList的构造方法,默认将DEFAULTCAPACITY_EMPTY_ELEMENTDATA空数组赋值给当前数组


```java
public boolean add(E e) {
  ensureCapacityInternal(size + 1);  // Increments modCount!!,每次传过去的值为size+1
  elementData[size++] = e;
  return true;
}//add方法
private void ensureCapacityInternal(int minCapacity) {
  ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));//比较elementData和minCapacity大小返回大的
}

private void ensureExplicitCapacity(int minCapacity) {
  modCount++;

  // overflow-conscious code
  if (minCapacity - elementData.length > 0)
      grow(minCapacity);
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
  if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
       return Math.max(DEFAULT_CAPACITY, minCapacity);//将这个数于默认的容量10进行比较,返回大的
  }
    return minCapacity;
}
//扩容的核心代码
private void grow(int minCapacity) {
  // overflow-conscious code
  int oldCapacity = elementData.length;
  int newCapacity = oldCapacity + (oldCapacity >> 1);//右移1位,相当于除以2
  if (newCapacity - minCapacity < 0)
      newCapacity = minCapacity;
  if (newCapacity - MAX_ARRAY_SIZE > 0)
      newCapacity = hugeCapacity(minCapacity);
  // minCapacity is usually close to size, so this is a win:
  elementData = Arrays.copyOf(elementData, newCapacity);
}
  • 结论:不调用add时ArrayList的容量为0,当调用add时,容量为10,当size为10时,ArrayList扩容,扩容大小为基础的1.5倍,即10*1.5=15,依次往下推。

三、Vector(用的不多)

import java.util.Enumeration;
import java.util.ListIterator;
import java.util.Vector;
public class VectorDemo {
    /**
     * 存储结构:数组 和ArrayList差不多,比ArrayList安全,但相对较慢
     * @param args
     */
    public static void main(String[] args) {
        Vector vector=new Vector();
        //1.添加
        vector.add("小米");
        vector.add("苹果");
        vector.add("华为");
        System.out.println(vector.size());
        System.out.println(vector);
        //2.删除
        //vector.remove(0);
        //vector.remove("苹果");
        //vector.clear();
        //System.out.println(vector);
        //3.遍历
        //ListIterator列表迭代器
        ListIterator lit = vector.listIterator();
        while(lit.hasNext()){
            System.out.println(lit.next());
        }
        //枚举器
        Enumeration enumeration = vector.elements();
        while (enumeration.hasMoreElements()){
            System.out.println(enumeration.nextElement());
        }
        //4.查找
        System.out.println(vector.contains("苹果"));
        System.out.println(vector.isEmpty());
        //5.其他方法
        System.out.println(vector.firstElement());
        System.out.println(vector.lastElement());
        System.out.println(vector.elementAt(0));//返回索引处的元素
    }
}

四、LinkedList

import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

public class LinkedListDemo01 {
    public static void main(String[] args) {
        LinkedList linkedList=new LinkedList();
        Student s1=new Student("韩邦胜",20);
        Student s2=new Student("韩胜",21);
        Student s3=new Student("韩邦",22);
        //添加
        linkedList.add(s1);
        linkedList.add(s2);
        linkedList.add(s3);
        System.out.println(linkedList.size());
        System.out.println(linkedList);
        //删除
//        linkedList.remove(0);
//        linkedList.remove(new Student("韩邦",22));
//        System.out.println(linkedList.size());
//        System.out.println(linkedList);
        //遍历
        //1.for
        System.out.println("---------for------------");
        for (int i = 0; i < linkedList.size(); i++) {
            System.out.println(linkedList.get(i));
        }
        //2.foreach
        System.out.println("---------foreach------------");
        for (Object obj:linkedList) {
            System.out.println(obj);
        }
        //3.iterator
        System.out.println("---------iterator------------");
        Iterator it = linkedList.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //4.listiterator
        System.out.println("---------listiterator------------");
        ListIterator lit = linkedList.listIterator();
        while(lit.hasNext()){
            System.out.println(lit.next());
        }
        //判断
        System.out.println(linkedList.contains(s1));
        System.out.println(linkedList.isEmpty());
        System.out.println(linkedList.indexOf(s1));
    }
}
  • LinkedList源码分析

    • size():大小
    • first:头结点
    • last:尾结点
    • add()方法
    public boolean add(E e) {
        linkLast(e);
        return true;
    }
    
    • linkLast(e)
    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++;
    }
    
    • 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;
        }
    }
    
    • 分析linkLast,当添加第一个元素时,last为空,所以l为空,newNode调用Node类的构造方法,前一个为空,后一个也为空,将newNode赋值给last,l==null,所以first也是newNode。size++。
    • 第二次add元素,last已经不是null了,newNode的前面指向last,并将last重新赋值为新的newNode,并将l的下个节点指向这个newNode,size++。
    • 双向链表结构
    • 删除的话只需要查到后断开那个链,接到下一个结点就行,因此比较快。

五、ArrayList和LinkedList区别

  • ArrayList开辟的空间是连续的
  • LinkedList开辟的空间不用是连续的

image-20220128152858931

posted @ 2022-02-25 10:35  是韩信啊  阅读(75)  评论(0编辑  收藏  举报