当前位置:   article > 正文

【JAVA学习笔记】53 - 集合-List类及其子类Collection、ArrayList、LinkedList类、Vector类

【JAVA学习笔记】53 - 集合-List类及其子类Collection、ArrayList、LinkedList类、Vector类

项目代码

https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter14/src/com/yinhai/collection_

https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter14/src/com/yinhai/list_

目录

项目代码

集合

一、引入

数组

集合

二、集合的框架体系

单列集合       

双列集合       

Collection类

一、Collection类接口和常用方法

二、Iterator迭代器

1.基本介绍

2.迭代器的执行原理

 3.增强for循环完成迭代器

 4.迭代器练习

三、List接口方法

1.List接口基本介绍

 2.List的常用方法

3.List练习

4.ListFor三种遍历方式与三种子类

5.List接口课堂练习

四、ArrayList 的底层结构和源码分析(建议多看看)

1.ArrayList的细节

2.ArrayList的源码分析(重点难点)

五、Vector类的底层结构和源码分析(建议多看看)

1.Vector的基本介绍

2.Vector和ArrayList的比较

​编辑        

六、LinkedList的底层结构和源码分析

1.LinkedList的说明

2.模拟双向链表

3.LinkedListCURD分析

增加

 删除

 4.ArrayList和inkedList的比较

如何选择ArrayList和LinkedList:


集合

一、引入

        前面我们保存多个数据使用的是数组,那么数组有不足的地方,我们分析一下。

数组

        1)长度开始时必须指定,而且一旦指定,不能更改

        2)保存的必须为同类型的元素

        3)使用数组进行增加元素的示意代码-比较麻烦


写出Person数组扩容示意代码。


                Person[] pers = new Person[1];
                per[0]=new Person();

                Person[] pers2 = new Person[pers.length+ 1]; //新创建数组
                for(){} //拷贝pers数组的元素到pers2
                pers2[pers2.length-1]=new Person();//添加新的对象

集合

1)可以动态保存任意多个对象,使用比较方便!

2)提供了一系列方便的操作对象的方法: add、remove、set、 get等

3)使用集合添加,删除新元素的示意代码-简洁了

二、集合的框架体系

集合主要分两组 单列和双列

单列集合       

        两个重要的两个子接口List        Set

双列集合       

        属于双列集合,存放K-V的数据

Collection类

一、Collection类接口和常用方法

Collection接口实现类的特点

public interface Collection<E> extends iterable <E>

1) collection实现子类可以存放多个元素, 每个元素可以是Object

2)有些Collection的实现类,可以存放重复的元素,有些不可以

3)有些Collection的实现类,有些是有序的(List),有些不是有序(Set)

4) Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的
 

  1. public class CollectionMethod {
  2. @SuppressWarnings({"all"})
  3. public static void main(String[] args) {
  4. List list = new ArrayList();
  5. //add:添加单个元素
  6. list.add("jack");
  7. list.add(10);//list.add(new Integer(10))对象
  8. list.add(true);
  9. System.out.println("list=" + list);
  10. //remove:删除指定元素
  11. //list.remove(0);//删除第一个元素
  12. list.remove(true);//指定删除某个元素
  13. System.out.println("list=" + list);
  14. //contains:查找元素是否存在
  15. System.out.println(list.contains("jack"));//T
  16. //size:获取元素个数
  17. System.out.println(list.size());//2
  18. //isEmpty:判断是否为空
  19. System.out.println(list.isEmpty());//F
  20. //clear:清空
  21. list.clear();
  22. System.out.println("list=" + list);
  23. //addAll:添加多个元素
  24. ArrayList list2 = new ArrayList();
  25. list2.add("红楼梦");
  26. list2.add("三国演义");
  27. list.addAll(list2);
  28. System.out.println("list=" + list);
  29. //containsAll:查找多个元素是否都存在
  30. System.out.println(list.containsAll(list2));//T
  31. //removeAll:删除多个元素
  32. list.add("聊斋");
  33. list.removeAll(list2);
  34. System.out.println("list=" + list);//[聊斋]
  35. }
  36. }

二、Iterator迭代器

Collection接口遍历元素方式1-使用Iterator(迭代器)

1.基本介绍

1) Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。

2)所有实现了Collection接的集合类都有个iterator(方法, 用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。

3) Iterator的结构

4) Iterator仅用于遍历集合,Iterator 本身并不存放对象。

2.迭代器的执行原理
 

Iterator iterator = coll.iterator(): //得到一个集合的迭代器

//hasNext():判断是否还有下一个元素
        while(iterator.hasNext()){

//next(:@下移②将下移以后集合位置上的元素返回
        System.out.println(iterator.next());

                

  1. public class CollectionIterator {
  2. @SuppressWarnings({"all"})
  3. public static void main(String[] args) {
  4. Collection col = new ArrayList();
  5. col.add(new Book("三国演义", "罗贯中", 10.1));
  6. col.add(new Book("小李飞刀", "古龙", 5.1));
  7. col.add(new Book("红楼梦", "曹雪芹", 34.6));
  8. System.out.println("col=" + col);
  9. //希望遍历该集合
  10. //1.先得到col对应的迭代器
  11. Iterator iterator = col.iterator();
  12. //2.使用while循环遍历
  13. while(iterator.hasNext()){//判断是否还有数据
  14. //返回下一个元素,类型是Object
  15. Object obj = iterator.next();
  16. System.out.println("obj" + obj);
  17. }
  18. //快捷键,快速的生成while循环->itit (Ctrl +J 可以显示快捷模版)
  19. //
  20. //3.当退出while循环后,这是iterator迭代器指向最后的元素
  21. //iterator.next();//NoSuchElementException
  22. //4.再次遍历需要重置我们的迭代器
  23. iterator = col.iterator();
  24. }
  25. }
  26. class Book {
  27. private String name;
  28. private String author;
  29. private double price;
  30. public Book(String name, String author, double price) {
  31. this.name = name;
  32. this.author = author;
  33. this.price = price;
  34. }
  35. public String getName() {
  36. return name;
  37. }
  38. public void setName(String name) {
  39. this.name = name;
  40. }
  41. public String getAuthor() {
  42. return author;
  43. }
  44. public void setAuthor(String author) {
  45. this.author = author;
  46. }
  47. public double getPrice() {
  48. return price;
  49. }
  50. public void setPrice(double price) {
  51. this.price = price;
  52. }
  53. @Override
  54. public String toString() {
  55. return "Book{" +
  56. "name='" + name + '\'' +
  57. ", author='" + author + '\'' +
  58. ", price=" + price +
  59. '}';
  60. }
  61. }

 3.增强for循环完成迭代器

增强for循环,可以代替iterator迭代器, 特点:增强for就是简化版的iterator本质样。只能用于遍历合或数组。

基本语法

for(元素类型元素名:集合名或数组名) {访问元素}

  1. public class CollectionFor {
  2. @SuppressWarnings({"all"})
  3. public static void main(String[] args) {
  4. Collection col = new ArrayList();
  5. col.add(new Book("三国演义", "罗贯中", 10.1));
  6. col.add(new Book("小李飞刀", "古龙", 5.1));
  7. col.add(new Book("红楼梦", "曹雪芹", 34.6));
  8. for (Object o : col) {
  9. System.out.println("book=" + o);
  10. }
  11. //1. 使用增强for, 在Collection集合
  12. //2. 增强for, 底层仍然是迭代器
  13. //3. 增强for可以理解成就是简化版本的 迭代器遍历
  14. //4. 快捷键方式 I
  15. // for (Object book : col) {
  16. // System.out.println("book=" + book);
  17. // }
  18. //增强for,也可以直接在数组使用
  19. // int[] nums = {1, 8, 10, 90};
  20. // for (int i : nums) {
  21. // System.out.println("i=" + i);
  22. // }
  23. }
  24. }

增强for, 底层仍然是迭代器

增强for可以理解成就是简化版本的 迭代器遍历

 4.迭代器练习

  1. public class CollectionExercise {
  2. @SuppressWarnings({"all"})
  3. public static void main(String[] args) {
  4. List list = new ArrayList();
  5. list.add(new Dog("小黑", 3));
  6. list.add(new Dog("大黄", 100));
  7. list.add(new Dog("大壮", 8));
  8. //先使用for增强
  9. for (Object dog : list) {
  10. System.out.println("dog=" + dog);
  11. }
  12. //使用迭代器
  13. System.out.println("===使用迭代器来遍历===");
  14. Iterator iterator = list.iterator();
  15. while (iterator.hasNext()) {
  16. Object dog = iterator.next();
  17. System.out.println("dog=" + dog);
  18. }
  19. }
  20. }
  21. /**
  22. * 创建 3个 Dog {name, age} 对象,放入到 ArrayList 中,赋给 List 引用
  23. * 用迭代器和增强for循环两种方式来遍历
  24. * 重写Dog 的toString方法, 输出name和age
  25. */
  26. class Dog {
  27. private String name;
  28. private int age;
  29. public Dog(String name, int age) {
  30. this.name = name;
  31. this.age = age;
  32. }
  33. public String getName() {
  34. return name;
  35. }
  36. public void setName(String name) {
  37. this.name = name;
  38. }
  39. public int getAge() {
  40. return age;
  41. }
  42. public void setAge(int age) {
  43. this.age = age;
  44. }
  45. @Override
  46. public String toString() {
  47. return "Dog{" +
  48. "name='" + name + '\'' +
  49. ", age=" + age +
  50. '}';
  51. }
  52. }

三、List接口方法

1.List接口基本介绍

        List接口是Collection接口的子接口

1) List集合类中元素有序(即添加顺序和取出顺序一致)、 且可重复

2) List集合中的每个元素都有其对应的顺序索引,即支持索引。

3) List容器中的元素都对应一 个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。

        List list = new ArrayList(;

4) JDK API中List接口的实现类有

 2.List的常用方法

        

  1. public class ListMethod {
  2. @SuppressWarnings({"all"})
  3. public static void main(String[] args) {
  4. List list = new ArrayList();
  5. list.add("张三丰");
  6. list.add("贾宝玉");
  7. //void add(int index, Object ele):在index位置插入ele元素
  8. //在index = 1的位置插入一个对象
  9. list.add(1, "韩顺平");
  10. System.out.println("list=" + list);
  11. //boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
  12. List list2 = new ArrayList();
  13. list2.add("jack");
  14. list2.add("tom");
  15. list.addAll(1, list2);
  16. System.out.println("list=" + list);
  17. //Object get(int index):获取指定index位置的元素
  18. //collection方法有
  19. //int indexOf(Object obj):返回obj在集合中首次出现的位置
  20. System.out.println(list.indexOf("tom"));//2
  21. //int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
  22. list.add("韩顺平");
  23. System.out.println("list=" + list);
  24. System.out.println(list.lastIndexOf("韩顺平"));
  25. // Object remove(int index):移除指定index位置的元素,并返回此元素
  26. list.remove(0);
  27. System.out.println("list=" + list);
  28. //Object set(int index, Object ele):设置指定index位置的元素为ele , 相当于是替换.
  29. list.set(1, "玛丽");//一定要存在才能替换
  30. System.out.println("list=" + list);
  31. //List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
  32. // 注意返回的子集合 fromIndex <= subList < toIndex [0,2)
  33. List returnlist = list.subList(0, 2);
  34. System.out.println("returnlist=" + returnlist);
  35. }
  36. }

3.List练习

        

  1. public class ListExercise {
  2. public static void main(String[] args) {
  3. List list = new ArrayList();
  4. for (int i = 0; i < 12; i++) {
  5. list.add("hello" + i);
  6. }//在索引为1插入一个元素
  7. list.add(1,"hspedu");
  8. System.out.println("list=" + list);//在abstractCollection内有toString方法
  9. //获得下标为4的元素
  10. System.out.println("第五个元素" + list.get(4));
  11. //删除下标为5的元素
  12. list.remove(5);
  13. System.out.println("list" + list);
  14. //修改第七个元素
  15. list.set(6,"三国演义");
  16. //使用迭代器
  17. for (Object o : list) {
  18. System.out.println(o);
  19. }
  20. Iterator iterator = list.iterator();
  21. while (iterator.hasNext()) {
  22. Object next = iterator.next();
  23. System.out.println(next);
  24. }
  25. }
  26. }

4.ListFor三种遍历方式与三种子类

        List的三种遍历方式while for增强 for普通

[ArrayList, LinkedList,Vector]三种运行类型。只要是实现List接口的子类都能这么遍历。(区别后面会讲)

//List 接口的实现子类 Vector LinkedList
List list = new ArrayList();
List list = new Vector();
List list = new LinkedList();

  1. public class ListFor {
  2. @SuppressWarnings({"all"})
  3. public static void main(String[] args) {
  4. //List 接口的实现子类 Vector LinkedList
  5. //List list = new ArrayList();//换成ArrayList代码也不会报错
  6. //List list = new Vector();//换成Vector也不会报错
  7. List list = new LinkedList();
  8. list.add("jack");
  9. list.add("tom");
  10. list.add("鱼香肉丝");
  11. list.add("北京烤鸭子");
  12. //遍历
  13. //1. 迭代器
  14. Iterator iterator = list.iterator();
  15. while (iterator.hasNext()) {
  16. Object obj = iterator.next();
  17. System.out.println(obj);
  18. }
  19. System.out.println("=====增强for=====");
  20. //2. 增强for
  21. for (Object o : list) {
  22. System.out.println("o=" + o);
  23. }
  24. System.out.println("=====普通for====");
  25. //3. 使用普通for
  26. for (int i = 0; i < list.size(); i++) {
  27. System.out.println("对象=" + list.get(i));
  28. }
  29. }
  30. }

5.List接口课堂练习

                

  1. public class ListExercise01 {
  2. @SuppressWarnings({"ALL"})
  3. public static void main(String[] args) {
  4. List list = new ArrayList();
  5. list.add(new Book("三国演义", "罗贯中", 10.1));
  6. list.add(new Book("小李飞刀", "古龙", 5.1));
  7. list.add(new Book("红楼梦", "曹雪芹", 34.6));
  8. list.add(new Book("活着", "余华", 12.4));
  9. list.add(new Book("3年模拟", "新华", 60.0));
  10. //如何对集合进行排序
  11. sort(list);
  12. for (Object o : list) {
  13. //直接sout(list)的话调用的是AbstactCoolection的toShtring方法,虽然也会调用对象的toString,但格式不对
  14. System.out.println(o);
  15. }
  16. }
  17. public static void sort(List list){
  18. for (int i = 0; i < list.size() - 1; i++) {
  19. for (int j = 0; j < list.size() - i - 1; j++) {
  20. //取出对象
  21. Book book = (Book)list.get(j);
  22. Book book1 = (Book)list.get(j + 1);
  23. if (book.getPrice() < book1.getPrice()){
  24. list.set(j,book1);
  25. list.set(j + 1,book);
  26. }
  27. }
  28. }
  29. }
  30. }
  31. class Book {
  32. private String name;
  33. private String author;
  34. private double price;
  35. public Book(String name, String author, double price) {
  36. this.name = name;
  37. this.author = author;
  38. this.price = price;
  39. }
  40. public String getName() {
  41. return name;
  42. }
  43. public void setName(String name) {
  44. this.name = name;
  45. }
  46. public String getAuthor() {
  47. return author;
  48. }
  49. public void setAuthor(String author) {
  50. this.author = author;
  51. }
  52. public double getPrice() {
  53. return price;
  54. }
  55. public void setPrice(double price) {
  56. this.price = price;
  57. }
  58. @Override
  59. public String toString() {
  60. return "名字=" + name + "\t\t作者=" + author + "\t\t价格=" + price;
  61. }
  62. }

四、ArrayList 的底层结构和源码分析(建议多看看)

1.ArrayList的细节

        1)permits all elements, including null,ArrayList可以加入null,并且多个

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

        3) ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码.,
在多线程情况下,不建议使用ArrayList

  1. public class ArrayListDetail {
  2. public static void main(String[] args) {
  3. //ArrayList 是线程不安全的, 可以看源码 没有 synchronized
  4. /*
  5. public boolean add(E e) {
  6. ensureCapacityInternal(size + 1); // Increments modCount!!
  7. elementData[size++] = e;
  8. return true;
  9. }
  10. */
  11. ArrayList arrayList = new ArrayList();
  12. arrayList.add(null);
  13. arrayList.add("jack");
  14. arrayList.add(null);
  15. arrayList.add("hsp");
  16. System.out.println(arrayList);
  17. }
  18. }

2.ArrayList的源码分析(重点难点)

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

        transient Object[] elementData;//tansient表示瞬间,将来这个被修饰的对象不会被序列化

2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10, 如需要再次扩容,则扩容elementData为1.5倍。//每次都会检测扩容

3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。

用下列源码debug看

  1. public class ArrayListSource {
  2. public static void main(String[] args) {
  3. //注意,注意,注意,Idea 默认情况下,Debug 显示的数据是简化后的,如果希望看到完整的数据
  4. //需要做设置.
  5. //使用无参构造器创建ArrayList对象
  6. ArrayList list = new ArrayList();
  7. // ArrayList list = new ArrayList(8);
  8. //使用for给list集合添加 1-10数据
  9. for (int i = 1; i <= 10; i++) {
  10. list.add(i);
  11. }
  12. //使用for给list集合添加 11-15数据
  13. for (int i = 11; i <= 15; i++) {
  14. list.add(i);
  15. }
  16. list.add(100);
  17. list.add(200);
  18. list.add(null);
  19. }
  20. }

源码流程图

IDEA在debug的时候会出现省略null空数据,可以设置显示

省略null数据可以设置显示

五、Vector类的底层结构和源码分析(建议多看看)

1.Vector的基本介绍

        1) Vector类的定义说明

                public class Vector<E>

                extends AbstractList<E>

                implements List<E>, RandomAccess, Cloneable, Serializable

        2) Vector底层也是一个对象数组, protected Object[] elementData;

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

                public synchronized E get(int index) {

                if (index > = elementCount)

                throw new ArrayIndexOutOfBoundsException(index);

                return elementData(index);

        4)在开发中,需要线程同步安全时,考虑使用Vector

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

2.Vector和ArrayList的比较


        

六、LinkedList的底层结构和源码分析

1.LinkedList的说明

        1) LinkedList实现了双向链表和双端队列特点

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

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

2.模拟双向链表

1) LinkedList底层维护了一个双向链表

                

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

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

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

                ​​​​​​​

        ​​​​​​​        

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

  1. public class LinkedList01 {
  2. public static void main(String[] args) {
  3. //模拟一个简单的双向链表
  4. Node jack = new Node("jack");
  5. Node tom = new Node("tom");
  6. Node hsp = new Node("老韩");
  7. //连接三个结点,形成双向链表(结点也叫对象
  8. //jack -> tom -> hsp
  9. jack.next = tom;
  10. tom.next = hsp;
  11. //hsp -> tom -> jack
  12. hsp.pre = tom;
  13. tom.pre = jack;
  14. Node first = jack;//让first引用指向jack,就是双向链表的头结点
  15. Node last = hsp; //让last引用指向hsp,就是双向链表的尾结点
  16. //演示,从头到尾进行遍历
  17. System.out.println("===从头到尾进行遍历===");
  18. while (true) {
  19. if(first == null) {
  20. break;
  21. }
  22. //输出first 信息
  23. System.out.println(first);
  24. first = first.next;
  25. }
  26. //演示,从尾到头的遍历
  27. System.out.println("====从尾到头的遍历====");
  28. while (true) {
  29. if(last == null) {
  30. break;
  31. }
  32. //输出last 信息
  33. System.out.println(last);
  34. last = last.pre;
  35. }
  36. //演示链表的添加对象/数据,是多么的方便
  37. //要求,是在 tom --------- 老韩直接,插入一个对象 smith
  38. //1. 先创建一个 Node 结点,name 就是 smith
  39. Node smith = new Node("smith");
  40. //下面就把 smith 加入到双向链表了
  41. smith.next = hsp;
  42. smith.pre = tom;
  43. hsp.pre = smith;
  44. tom.next = smith;
  45. //让first 再次指向jack
  46. first = jack;//让first引用指向jack,就是双向链表的头结点
  47. System.out.println("===从头到尾进行遍历===");
  48. while (true) {
  49. if(first == null) {
  50. break;
  51. }
  52. //输出first 信息
  53. System.out.println(first);
  54. first = first.next;
  55. }
  56. last = hsp; //让last 重新指向最后一个结点
  57. //演示,从尾到头的遍历
  58. System.out.println("====从尾到头的遍历====");
  59. while (true) {
  60. if(last == null) {
  61. break;
  62. }
  63. //输出last 信息
  64. System.out.println(last);
  65. last = last.pre;
  66. }
  67. }
  68. }
  69. //定义一个Node 类,Node对象,表示双向链表的一个结点
  70. class Node {
  71. public Object item; //真正存放数据
  72. public Node next; //指向后一个结点(下一个
  73. public Node pre; //指向前一个结点(上一个
  74. public Node(Object name) {
  75. this.item = name;
  76. }
  77. public String toString() {
  78. return "Node name=" + item;
  79. }
  80. }

        ​​​​​​​        

        ​​​​​​​        ​​​​​​​

3.LinkedListCURD分析

增加

 删除

  1. public boolean add(E e) {
  2. linkLast(e);
  3. return true;
  4. }
  5. 4.将新的结点,加入到双向链表的最后
  6. void linkLast(E e) {
  7. final Node<E> l = last;
  8. final Node<E> newNode = new Node<>(l, e, null);
  9. last = newNode;
  10. if (l == null)
  11. first = newNode;
  12. else
  13. l.next = newNode;
  14. size++;
  15. modCount++;
  16. }
  17. */
  18. //演示一个删除结点的
  19. linkedList.remove(); // 这里默认删除的是第一个结点
  20. //linkedList.remove(2);
  21. System.out.println("linkedList=" + linkedList);
  22. /*
  23. 老韩读源码 linkedList.remove(); // 这里默认删除的是第一个结点
  24. 1. 执行 removeFirst
  25. public E remove() {
  26. return removeFirst();
  27. }
  28. 2. 执行
  29. public E removeFirst() {
  30. final Node<E> f = first;
  31. if (f == null)
  32. throw new NoSuchElementException();
  33. return unlinkFirst(f);
  34. }
  35. /*
  36. 3. 执行 unlinkFirst, 将 f 指向的双向链表的第一个结点拿掉
  37. private E unlinkFirst(Node<E> f) {
  38. // assert f == first && f != null;
  39. final E element = f.item;
  40. final Node<E> next = f.next;
  41. f.item = null;
  42. f.next = null; // help GC
  43. first = next;
  44. if (next == null)
  45. last = null;
  46. else
  47. next.prev = null;
  48. size--;
  49. modCount++;
  50. return element;
  51. }
  52. */
  53. //修改某个结点对象
  54. linkedList.set(1, 999);
  55. System.out.println("linkedList=" + linkedList);
  56. //得到某个结点对象
  57. //get(1) 是得到双向链表的第二个对象
  58. Object o = linkedList.get(1);
  59. System.out.println(o);//999
  60. //因为LinkedList 是 实现了List接口, 遍历方式
  61. System.out.println("===LinkeList遍历迭代器====");
  62. Iterator iterator = linkedList.iterator();
  63. while (iterator.hasNext()) {
  64. Object next = iterator.next();
  65. System.out.println("next=" + next);
  66. }
  67. System.out.println("===LinkeList遍历增强for====");
  68. for (Object o1 : linkedList) {
  69. System.out.println("o1=" + o1);
  70. }
  71. System.out.println("===LinkeList遍历普通for====");
  72. for (int i = 0; i < linkedList.size(); i++) {
  73. System.out.println(linkedList.get(i));
  74. }
  75. }
  76. }

 4.ArrayList和inkedList的比较

如何选择ArrayList和LinkedList:

        两个都是线程不安全的

1)如果我们改查的操作多,选择ArrayList

2)如果我们增删的操作多,选择LinkedList

3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList

4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另外一个模块是LinkedList.
 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/77338
推荐阅读
相关标签
  

闽ICP备14008679号