• List集合


    List集合的学习

    1. 特点:有序(存储顺序和取出顺序是一致的),可重复

      		List A = new ArrayList();
              A.add("a");
              A.add("b");
              A.add("c");
              A.add("d");
              A.add("d");
              for (int i = 0; i < A.size(); i++) {
                  System.out.println(A.get(i));
              }
      
    2. 关于 迭代器 与Collection的区别

      1. 返回的是自己特有的 ListIterator extends Iterator
      2. 增强了 iterator 的方法,不止于 hasNext() next() remove()
      3. 列表有双向列表,所有增加了 pervious() hasPervious();
      4. add(),set() 可以添加、设置元素

    List 集合常用子类

    1. List集合的常用子类 三个
      1. ArrayList
        • 底层的数据结构是数组。线程不安全的
      2. LinkedList
        • 底层结构是链表。线程不安全的
      3. Vector
        • 底层结构是数组。线程安全的

    Set 集合常用的子类

    1. HashSet
      • 底层结构是哈希表(每一个元素为一个链表的数组)
    2. TreeSet
      • 底层结构是红黑树(是一个自平衡的二叉树)
      • 保证元素的排序方式
    3. LinkedHashSet
      • 底层结构是哈希表和链表

    ArrayList

    1. 属性

      1. 初始化容量

        private static final int DEFAULT_CAPACITY = 10;
        
      2. 指定构造函数容量为0时返回的空数组

        private static final Object[] EMPTY_ELEMENTDATA = {};
        
      3. 用户不指定,默认返回的空数组,也就是空构造

        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
        
      4. ArrayList的实际大小

        private int size;
        
      5. 底层数组:当第一次Add元素时,这个数组会扩容到初始化容量DEFAULT_CAPACITY

        transient Object[] elementData; // non-private to simplify nested class access
        
    2. 构造函数方面

      1. 如果用户指定了初始容量,那么就会构造处对应容量的对象数组,若初始化容量为0时,就返回的是 EMPTY_ELEMENTDATA
      2. 如果用户不指定初始容量(空构造),返回的是 DEFAULTCAPACITY_EMPTY_ELEMENTDATA
    3. Add方法

      1. add(E e) 直接添加元素的

        1. 注意点

          1. 检查是否需要扩容
          2. 插入元素
        2. 底层步骤

          1. 检查容量是否需要扩容

          2. 容量足够,那么直接添加

          3. 容量不足,扩容 核心是根据 size 和 length 判断,个数-长度>0那么就需要扩容

            1. 扩容到原来的1.5倍
            2. 如果第一次扩容的容量,还是比minCapacity小,那么直接扩容到minCapacity
          4.  private void grow(int minCapacity) {
                    // overflow-conscious code
                    int oldCapacity = elementData.length;
                    int newCapacity = oldCapacity + (oldCapacity >> 1);
                    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);
                }
            
      2. add(int index, E e) 将元素插入到指定的位置

        1. 注意点

          1. 检查角标
          2. 检查是否需要扩容
          3. 插入元素
        2. 底层步骤

          1. 检查角标是否越界

            1. private void rangeCheckForAdd(int index) {
                      if (index > size || index < 0)
                          throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
                  }
              
            2. 如果插入位置,都已经超出了元素个数了,或者为负数,都是越界的情况

          2. 检查是否需要扩容

            1. 调用的就是 add 的扩容检查方法
          3. 调用

             System.arraycopy(elementData, index, elementData, index + 1,
                                     size - index);
            

            拷贝数组,其实本质就是所有的下表往后移了一位的处理

          4. 在指定位置赋值元素,size++

            1. elementData[index] = element;
                      size++;
              
      3. get(int index) 获取指定位置的元素

        1. 注意点

          1. 检查角标
          2. 返回元素
        2. 底层步骤

          1. 检查角标,调用的就是 add(index,e)的检查越界的方法

          2. 返回元素

            1. 不是直接底层数组[下标]

            2. 而是又包了一层,可能是做后期的扩展

              1. E elementData(int index) {
                        return (E) elementData[index];
                    }
                
              2. public E get(int index) {
                        rangeCheck(index);
                
                        return elementData(index);
                    }
                
      4. set(int index, E e) 设置指定位置的元素

        1. 注意点

          1. 检查角标
          2. 替代元素
          3. 返回旧值
        2. 底层实现步骤

          1. 检查角标,同add(index,e)

          2. 替代元素

            1. 让一个 变量等于 索引处的值

              E oldValue = elementData(index);
              
            2. 替换索引处的元素

              elementData[index] = element;
              
            3. 返回旧值

              return oldValue;
              
            4. 源码

              public E set(int index, E element) {
                      rangeCheck(index);
              
                      E oldValue = elementData(index);
                      elementData[index] = element;
                      return oldValue;
              }
              
      5. remove(int index) 删除指定位置的元素

        1. 注意点

          1. 检查角标
          2. 删除元素
          3. 计算出需要移动的个数并且移动
          4. 设置为 null,让GC回收
          5. 返回删除元素
        2. 底层实现

          1. 检查角标,同add(index, e)

          2. 删除元素

            1. 通过数组拷贝,index位置直接被下一个覆盖带掉
          3. 计算移动个数

            int numMoved = size - index - 1;
            
  • 相关阅读:
    Chapter 5. 集合---(ArrayList、Stack、queue、哈希表)
    Chapter 4. 数组
    第一章 代码无错就是优?——简单工厂模式
    条款34:区分接口继承和实现继承
    条款33:避免遮掩继承而来的名称
    条款32:确定你的public继承塑模出is-a关系
    条款12:复制对象时勿忘其每一部分
    A:魔兽世界之一:备战
    条款09:绝不在构造和析构过程中调用virtual函数
    7、数值算法
  • 原文地址:https://www.cnblogs.com/JQ04/p/15092886.html
Copyright © 2020-2023  润新知