zoukankan      html  css  js  c++  java
  • Collection 集合类

    ArrayList:

    基于动态数组的List

    它有两个重要的变量,size为存储的数据的个数、elementData 数组则是arraylist 的基础,因为他的内部就是通过这个数组来存储数据的。

    private int size;

    private transient Object[] elementData;

    优点:

    1,随机访问  调用get()、set()的时间复杂度为O(1),很高效

    public E get(int index) {
            rangeCheck(index);
    
            return elementData(index); //内部通过数组索引获取数据,所以高效
     }
    
    public E set(int index, E element) {
            rangeCheck(index);
    
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
    }

    2,尾部添加  add(E e)E为泛型,影响因素为扩容,扩容大小为1.5倍,需要进行内部数组的复制

     public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
     }

    缺点:

    1,删除数据的效率相对较低,时间复杂度O(n)  主要影响因素为数据移动和遍历数组

    public boolean remove(Object o) {
            if (o == null) {
                for (int index = 0; index < size; index++)
                    if (elementData[index] == null) { //遍历数组寻找元素,删除时索引之后的数据都要向前移动一位
                        fastRemove(index);
                        return true;
                    }
            } else {
                for (int index = 0; index < size; index++)
                    if (o.equals(elementData[index])) {
                        fastRemove(index);
                        return true;
                    }
            }
            return false;
     }


        public E remove(int index) {
            rangeCheck(index);
    
            modCount++;
            E oldValue = elementData(index);
    
            int numMoved = size - index - 1;
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved); //删除时索引后的所有数据向前移动一位
            elementData[--size] = null; // clear to let GC do its work
    
            return oldValue;
        }

    2,头部添加元素  时间复杂度O(n) ,影响因素数据移动

     public void add(int index, E element) {
            rangeCheckForAdd(index);
    
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            System.arraycopy(elementData, index, elementData, index + 1,
                             size - index);  //索引及之后的数据都要向后移动一位
            elementData[index] = element;
            size++;
    }

    3, 查找元素  indexof() 时间复杂度O(n),影响因素遍历数组

     public int indexOf(Object o) {
            if (o == null) {
                for (int i = 0; i < size; i++)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = 0; i < size; i++)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
     }

     LinkedList:

    基于双向链表

    三个重要的变量,1、int size   2、Node<E> first   3、Node<E> last

    size指LinkedList存储的元素的个数,first 指头结点,last 指尾结点

    ArrayList 基于动态数组,需要分配特定的存储空间、内存地址连续。

    LinkedList 基于双向链表,不需要分配特定存储空间、内存不连续,通过结点的头尾指针连接前后结点。

    优点:

    1,头部插入,删除效率高  时间复杂度O(1)  他不需要像ArrayList 那样要移动头部之后的所有元素

    private void linkFirst(E e) {
            final Node<E> f = first;
            final Node<E> newNode = new Node<>(null, e, f); //新建一个结点,前结点为null,元素 e,后结点为 f
            first = newNode;
            if (f == null)
                last = newNode;
            else
                f.prev = newNode;
            size++;
            modCount++;
     }
     private E unlinkFirst(Node<E> f) {
            // assert f == first && f != null;
            final E element = f.item;
            final Node<E> next = f.next;
            f.item = null;
            f.next = null; // help GC,清空元素和尾指针
            first = next;  //此结点的后继结点置为头结点
            if (next == null)
                last = null;
            else
                next.prev = null; //
            size--;
            modCount++;
            return element;
    }

    2,尾部插入、删除  效率很高 时间复杂度O(1),相对于ArrayList来说不用扩容

    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++;
    }

    缺点:

    1,随机访问  LinkedList的随机访问访问方面比较慢,时间复杂度O(n/2) 而ArrayList的随机访问为O(1)

    Node<E> node(int index) {
            // assert isElementIndex(index);
        // 访问时,先获取该位置的结点,然后返回结点的值
            if (index < (size >> 1)) { // 如果位置小于LinkedList元素个数的一半,则从头开始遍历,否则从后开始遍历,这也是时间复杂度为n/2的原因
                Node<E> x = first;
                for (int i = 0; i < index; i++)
                    x = x.next;
                return x;
            } else {
                Node<E> x = last;
                for (int i = size - 1; i > index; i--)
                    x = x.prev;
                return x;
    }

    2,查找元素  和ArrayList 一样需要遍历整个list,时间复杂度为O(n)

    public int indexOf(Object o) {
            int index = 0;
            if (o == null) {
                for (Node<E> x = first; x != null; x = x.next) {
                    if (x.item == null)
                        return index;
                    index++;
                }
            } else {
                for (Node<E> x = first; x != null; x = x.next) {
                    if (o.equals(x.item))
                        return index;
                    index++;
                }
            }
            return -1;
        }

    3,中间部分插入和删除  时间复杂度为O(n),影响原因需要先定位到指定元素。定位后修改的效率很高

     void linkBefore(E e, Node<E> succ) {
            // assert succ != null;
            final Node<E> pred = succ.prev;
            final Node<E> newNode = new Node<>(pred, e, succ);
            succ.prev = newNode;
            if (pred == null)
                first = newNode;
            else
                pred.next = newNode;
            size++;
            modCount++;
        }

    LinkedList在执行中间插入和删除时比ArrayList高效,随机访问反面比较逊色。 

    向前遍历List,不修改List对象本身,可以用foreach

    Iterator 只能向前移动,可以用next(),和remove()联合起来删除List中的对象

     1 public static void main(String[] args) {
     2         List<Integer> iList=new ArrayList<>();
     3         for (int i = 0; i < 8; i++) {
     4             iList.add(i);
     5         }
     6         
     7         for (Integer i : iList) {
     8             System.out.println(i);
     9         }              //foreach 遍历list
    10         
    18         Iterator<Integer> iterator=iList.iterator();
    19         while (iterator.hasNext()) {
    20             iterator.next();
    21             iterator.remove();    //迭代器遍历list,并进行删除
    22         }
    23         System.out.println(iList);
    24         
    25     }

    listIterator只能用于list类的访问,可以双向移动

    TreeSet将元素储存在红-黑树,数据结构中。HashSet使用散列函数。LinkedHashSet使用散列和链表维护插入顺序。

  • 相关阅读:
    第二阶段冲刺站立会议03
    第二阶段冲刺会议02
    第二阶段冲刺站立会议01(附第12周进度条)
    课堂练习,找水王(附第十一周进度条)
    输入法的评价
    描绘用户场景并将典型用户和用户场景描述(附第十周进度条)
    每日站立会议09,10
    第九周进度条
    团队报告
    个人记账软件(团队成员介绍和软件介绍)
  • 原文地址:https://www.cnblogs.com/peng111/p/5694281.html
Copyright © 2011-2022 走看看