• 【Java】集合(一)单列集合List


    1.集合

    可以动态保存任意多个对象,并提供了一系列的操作对象的方法:add、remove、set、get等。

    2.集合框架体系

    分为两大类:

    单列集合和双列集合

    3.List接口基本介绍

    List接口是Collection接口的子接口

    List集合类中元素有序可重复支持索引,List容器中的元素都对应一个整数型的序号,可以根据序号存取容器中的元素。

    List 集合里添加了一些根据索引来操作集合元素的方法

    1) void add(int index,Obiect ele):在index位置插入ele元素

    2)boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来

    3)Object get(int index):获取指定index位置的元素

    4)int indexof(Obiect obi):返回obi在集合中首次出现的位置

    5)int lastlndexof(Obiect obi):返回obi在当前集合中未次出现的位置

    6)Object remove(int index):移除指定index位置的元素,并返回此元素

    7)Object set(int index, Object ele):设置指定index位置的元素为ele相当于是替换

    8)List subList(int fromIndex, int tolndex):返回从fromIndex到tolndex位置的子集合

    例子

    1. List list=new ArrayList();
    2. //插入
    3. list.add(100);
    4. list.add(3);
    5. list.add("a");
    6. System.out.println(list);
    7. //删除
    8. list.remove(1);//默认按索引删除,索引从0开始
    9. list.remove(new Integer(100));//按指定元素删除,需要传入对象才行
    10. System.out.println(list);
    11. //修改
    12. list.set(0,"aaa");
    13. System.out.println(list);

    List的三种遍历方式

    方式一:使用iterator

    1. Iterator iter=list.iterator();
    2. while(iter.hasNext()) {
    3. Object o=iter.next();
    4. System.out.println(o);
    5. }

    方式二:使用增强for

    1. for(Object o:list) {
    2. System.out.println(o);
    3. }

    方式三:使用普通for

    1. for(int i=0;i<list.size();i++) {
    2. Object o=list.get(i);
    3. System.out.println(o);
    4. }

    4.ArrayList底层结构和源码分析

    基本介绍:

    1)ArrayList可以加入多个null

    2)ArrayList是由数组实现数据存储的

    3)ArrayList是线程不安全的,原因看源码没有synchronized

    ArrayList底层操作机制源码分析

    1)ArrayList中维护了一个Object类型的数组elementData。

    transient Object[] elementData; //transient 表示瞬间,短暂的,表示该属性不会被序列号

    2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
    3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容则直接扩容elementData为1.5倍。

    5.Vector底层结构和源码解剖

    基本介绍:

    1) Vector底层也是一个对象数组,protected Objectl] elementData;

    2) Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized

    1. //1. new Vector() 底层
    2. /*
    3. public Vector() {
    4. this(10);
    5. }
    6. 补充:如果是 Vector vector = new Vector(8);
    7. 走的方法:
    8. public Vector(int initialCapacity) {
    9. this(initialCapacity, 0);
    10. }
    11. 2. vector.add(i)
    12. 2.1 //下面这个方法就添加数据到 vector 集合
    13. public synchronized boolean add(E e) {
    14. modCount++;
    15. ensureCapacityHelper(elementCount + 1);
    16. elementData[elementCount++] = e;
    17. return true;
    18. }
    19. 2.2 //确定是否需要扩容 条件 : minCapacity - elementData.length>0
    20. private void ensureCapacityHelper(int minCapacity) {
    21. // overflow-conscious code
    22. if (minCapacity - elementData.length > 0)
    23. grow(minCapacity);
    24. }
    25. 2.3 //如果 需要的数组大小 不够用,就扩容 , 扩容的算法
    26. //newCapacity = oldCapacity + ((capacityIncrement > 0) ?
    27. //
    28. capacityIncrement : oldCapacity);
    29. //就是扩容两倍.
    30. private void grow(int minCapacity) {
    31. // overflow-conscious code
    32. int oldCapacity = elementData.length;
    33. int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
    34. capacityIncrement : oldCapacity);
    35. if (newCapacity - minCapacity < 0)
    36. newCapacity = minCapacity;
    37. if (newCapacity - MAX_ARRAY_SIZE > 0)
    38. newCapacity = hugeCapacity(minCapacity);
    39. elementData = Arrays.copyOf(elementData, newCapacity);
    40. }

    6.LinkedList底层结构

    LinkedList的全面说明
    1)LinkedList底层实现了双向链表和双端队列特点

    2)可以添加任意元素(元素可以重复),包括null

    3)线程不安全,没有实现同步

     LinkedList的底层操作机制
    1)LinkedList底层维护了一个双向链表

    2) LinkedList中维护了两个属性first和last分别指向 首节点和尾节点

    3)每个节点 (Node对象) ,里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表

    4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高

    5)模拟一个简单的双向链表

    1. /* 1. LinkedList linkedList = new LinkedList();
    2. public LinkedList() {}
    3. 2. 这时 linkeList 的属性 first = null last = null
    4. 3. 执行 添加
    5. public boolean add(E e) {
    6. linkLast(e);
    7. return true;
    8. }
    9. 4.将新的结点,加入到双向链表的最后
    10. void linkLast(E e) {
    11. final Node<E> l = last;
    12. final Node<E> newNode = new Node<>(l, e, null);
    13. last = newNode;
    14. if (l == null)
    15. first = newNode;
    16. else
    17. l.next = newNode;
    18. size++;
    19. modCount++;
    20. }
    21. */
    22. /* linkedList.remove(); // 这里默认删除的是第一个结点
    23. 1. 执行 removeFirst
    24. public E remove() {
    25. return removeFirst();
    26. }
    27. 2. 执行
    28. public E removeFirst() {
    29. final Node<E> f = first;
    30. if (f == null)
    31. throw new NoSuchElementException();
    32. return unlinkFirst(f);
    33. }
    34. 3. 执行 unlinkFirst, 将 f 指向的双向链表的第一个结点拿掉
    35. private E unlinkFirst(Node<E> f) {
    36. // assert f == first && f != null;
    37. final E element = f.item;
    38. final Node<E> next = f.next;
    39. f.item = null;
    40. f.next = null; // help GC
    41. first = next;
    42. if (next == null)
    43. last = null;
    44. else
    45. next.prev = null;
    46. size--;
    47. modCount++;
    48. return element;
    49. }
    50. */

  • 相关阅读:
    DITA-OT 4.0新特性 - PDF themes,定制PDF样式的新方法
    python从入门到出家(五)循环语句
    Nginx的Map模块
    【Text2SQL 论文】T5-SR:使用 T5 生成中间表示来得到 SQL
    内存问题难定位,那是因为你没用 ASAN
    Oracle Unifier 22.12 ~ 23.10 功能改进清单表
    滴滴发布十一大数据:延边出行需求上涨280% 西部省份成旅游热点
    【Python】python中多进程处理
    9.2 Windows钩子
    Vitalik:Layer2 是以太坊社区文化的延伸
  • 原文地址:https://blog.csdn.net/weixin_63357306/article/details/134369539