2020 10.29曾宇欣

心得体会:

前端的东西已经遗忘的差不多了,急需回忆。tomcat的使用也不熟悉,还需要多了解。

知识点:

今日复习:

一、集合:

java 中针对数组的缺陷(不可修改长度),提供了一种比数组灵活,使用更方便的接口和类,它们位于 java.until 包,称为集合框架

image-20201020221418594

image-20201021223736523

  1. java.lang.Iterable

    Iterable 接口,凡是实现了此接口的对象都能称为 for-each-loop 的目标。

    此接口会在之后单独总结

  2. java.util.Collection

    public interface Collection<E> extends Iterable<E>
    

    从类声明中我们可以看到,Collection接口继承了Iterable接口。意味着Collection接口的类也实现了Iterable接口,可以成为for-each-loop的循环对象。

    • Collection集合的方法

      public boolean add(E e) //在集合末尾添加元素
      public boolean remove(Object o) //若本类集合中有值与o相等,则删除该元素
      public void clear() //清除本类集合中的所有元素,集合为空
      public contains(Object o) //判断集合中是否包含某元素
      public boolean isEmpty() //判断集合是否为空
      public int size() //返回集合中的元素个数
      public Boolean addAll(Collection c) //将一个集合c中的元素,全部添加到另一个集合中去
      public Object[] toArray() //返回一个包含本类集合中的所有元素的数组,数组类型为,Object[]
  3. Collection 之ArrayList:

    • ArrayList是实现List接口的动态数组,数组大小可变。

    • ArrayList允许存储null在内的所有元素

    • ArrayList的初始容量是 10 ,并且容量会自动增长,在每次添加元素的时候,ArrayList会自动检查是否需要扩容,扩容操作带来数据向新数组的重新拷贝。如果我们知道具体业务的数量,在构造ArrayList的时候给它指定一个初始长度,这样就会减少扩容时数据的拷贝问题。

    • ArrayList是非线程安全的

      ArrayList的构造函数

      ArrayList() //默认构造函数
      ArrayList(int initialCapacity) //构造一个具有指定初始容量的空列表
      ArrayList(Collection<? extends E> c) //构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的

      ArrayList添加元素操作:

      add(E e) //将指定元素添加到末尾
      //源码分析
      public boolean add(E e) {
      ensureCapacity(size + 1); // Increments modCount!!
      elementData[size++] = e;
      return true;
      }
      //这里ensureCapacity()方法是对ArrayList集合进行扩容操作,elementData(size++) = e,将列表末尾元素指向e。
      add(int index, E element) //将指定元素插入此列表的指定位置
      public void add(int index, E element) {
      //判断索引位置是否正确
      if (index > size || index < 0)
      throw new IndexOutOfBoundsException(
      "Index: "+index+", Size: "+size);
      //扩容检测
      ensureCapacity(size+1);
      /*
      * 对源数组进行复制处理(位移),从index + 1到size-index。
      * 主要目的就是空出index位置供数据插入,
      * 即向右移动当前位于该位置的元素以及所有后续元素。
      */
      System.arraycopy(elementData, index, elementData, index + 1,
      size - index);
      //在指定位置赋值
      elementData[index] = element;
      size++;
      }
      addAll(Collection<? extends E> c)://按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。
      public boolean addAll(Collection<? extends E> c) {
      // 将集合C转换成数组
      Object[] a = c.toArray();
      int numNew = a.length;
      // 扩容处理,大小为size + numNew
      ensureCapacity(size + numNew); // Increments modCount
      System.arraycopy(a, 0, elementData, size, numNew);
      size += numNew;
      return numNew != 0;
      }
      addAll(int index, Collection<? extends E> c)://从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。
      public boolean addAll(int index, Collection<? extends E> c) {
      //判断位置是否正确
      if (index > size || index < 0)
      throw new IndexOutOfBoundsException("Index: " + index + ", Size: "
      + size);
      //转换成数组
      Object[] a = c.toArray();
      int numNew = a.length;
      //ArrayList容器扩容处理
      ensureCapacity(size + numNew); // Increments modCount
      //ArrayList容器数组向右移动的位置
      int numMoved = size - index;
      //如果移动位置大于0,则将ArrayList容器的数据向右移动numMoved个位置,确保增加的数据能够增加
      if (numMoved > 0)
      System.arraycopy(elementData, index, elementData, index + numNew,
      numMoved);
      //添加数组
      System.arraycopy(a, 0, elementData, index, numNew);
      //容器容量变大
      size += numNew;
      return numNew != 0;
      }
      set(int index, E element)://用指定的元素替代此列表中指定位置上的元素。
      public E set(int index, E element) {
      //检测插入的位置是否越界
      RangeCheck(index);
      E oldValue = (E) elementData[index];
      //替代
      elementData[index] = element;
      return oldValue;
      }

      ArrayList的删除操作:

      remove(int index)://移除此列表中指定位置上的元素。
      public E remove(int index) {
      //位置验证
      RangeCheck(index);
      modCount++;
      //需要删除的元素
      E oldValue = (E) elementData[index];
      //向左移的位数
      int numMoved = size - index - 1;
      //若需要移动,则想左移动numMoved位
      if (numMoved > 0)
      System.arraycopy(elementData, index + 1, elementData, index,
      numMoved);
      //置空最后一个元素
      elementData[--size] = null; // Let gc do its work
      return oldValue;
      }
      remove(Object o)://移除此列表中首次出现的指定元素(如果存在)。
      public boolean remove(Object o) {
      //因为ArrayList中允许存在null,所以需要进行null判断
      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;
      }
      removeRange(int fromIndex, int toIndex)://移除列表中索引在 fromIndex(包括)和 toIndex(不包括)之间的所有元素。
      protected void removeRange(int fromIndex, int toIndex) {
      modCount++;
      int numMoved = size - toIndex;
      System
      .arraycopy(elementData, toIndex, elementData, fromIndex,
      numMoved);
      // Let gc do its work
      int newSize = size - (toIndex - fromIndex);
      while (size != newSize)
      elementData[--size] = null;
      }

      ArrayList的扩容操作:

      在上面的新增方法的源码中我们发现每个方法中都存在这个方法:ensureCapacity(),该方法就是ArrayList的扩容方法。在前面就提过ArrayList每次新增元素时都会需要进行容量检测判断,若新增元素后元素的个数会超过ArrayList的容量,就会进行扩容操作来满足新增元素的需求。所以当我们清楚知道业务数据量或者需要插入大量元素前,我可以使用ensureCapacity来手动增加ArrayList实例的容量,以减少递增式再分配的数量。

      public void ensureCapacity(int minCapacity) {
           //修改计时器
      modCount++;
      //ArrayList容量大小
      int oldCapacity = elementData.length;
      /*
      * 若当前需要的长度大于当前数组的长度时,进行扩容操作
      */
      if (minCapacity > oldCapacity) {
      Object oldData[] = elementData;
      //计算新的容量大小,为当前容量的1.5倍
      int newCapacity = (oldCapacity * 3) / 2 + 1;
      if (newCapacity < minCapacity)
      newCapacity = minCapacity;
      //数组拷贝,生成新的数组
      elementData = Arrays.copyOf(elementData, newCapacity);
      }
      }

      选择扩容1.5倍是因为,1.5倍是最好的倍数,对资源利用率最高

List的三个子类的特点:

  • ArrayLIst的底层数据结构是数组,查询块,增删慢。非线程安全,效率高。

  • Vector的底层数据结构是数组,查询快,增删慢。线程安全,效率低。

  • Vector相对于ArrayList查询效率低,相对于LinkedList增删慢。

  • LinkedList底层数据结构是链表,查询慢,增删快。非线程安全,效率高。

  • 查询多使用ArrayList

  • 增删多使用LinkedList

  • 都多使用ArrayList

    一、HashSet定义:

    public class HashSet<E>
      extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable

    HashSet继承AbstractSet类,实现Set、Cloneable、Serializable接口。其中AbstractSet提供 Set 接口的骨干实现,从而最大限度地减少了实现此接口所需的工作。Set接口是一种不包括重复元素的Collection,它维持它自己的内部排序,所以随机访问没有任何意义。

    二、方法:

    // iterator()方法返回对此 set 中元素进行迭代的迭代器。返回元素的顺序并不是特定的。底层调用HashMap的keySet返回所有的key,这点反应了HashSet中的所有元素都是保存在HashMap的key中,value则是使用的PRESENT对象,该对象为static final。
    public Iterator<E> iterator() {
    return map.keySet().iterator();
    }
    //size() 返回set中元素的数量
    public int size(){}
    //判断HashSet是否为空
    public boolean isEmpty(){}
    //判断某个元素是否在HashSet中
    public boolean contains(Object o){}
    //移除指定元素
    public boolean remove(Object o){}
    //移除HashSet中的所有元素
    public void clear(){}

    由于HashSet底层使用了HashMap实现

标签

评论

this is is footer