第十五节 集合 (二) List

1. List 接口

1.1 概述

  1. Collection 集合可以分为两大类:ListSet
  2. 其中List集合,操作者可以控制添加 元素的位置,用户可以根据 元素的索引 来访问元素。

1.2 List 特点

  1. 元素有序。
  2. 可以存放重复的元素。
  3. 元素有下标(索引)。

1.3 List 方法

  1. 你会发现 List 接口中的方法方法中有很多都是Collection的接口中的方法。
  2. List ,也有自己的独特方法
    • 是不是发现了点什么? List中大多数方法都是可以 按照索引进行操作 的。
名称作用
void add(E e)向集合中添加元素
void add(int index,Object element)根据索引,在指定位置添加元素
boolean contains(Object o)如果此列表包含指定的元素,则返回 true
Object get(int index):获取指定索引处元素,从0开始
E set(int index, E element)根据索引,替换该位置元素
int indexOf(Object o)返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
int lastIndexOf(Object o)返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
Object remove(int index)根据索引删除元素
boolean remove(Object o)从列表中删除指定元素的第一个出现(如果存在)(可选操作)。
Object set(int index,Object element)根据索引修改元素
List<E> subList(int fromIndex, int toIndex)从集合中截取,列表中指定的 fromIndex (含)和 toIndex(不含)之间的新集合。
ListIterator listIterator(int index)从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。
ListIterator listIterator()返回列表中的列表迭代器(按适当的顺序)

1.4 课堂练习

1.4.1 练习:List 方法测试

  1. 根据方法特点,测试List常用方法。
    • 有自己的方法也有 Collection 方法。
public class Test_List {
    public static void main(String[] args) {
        //1.创建对象测试方法。
        List<String> list = new ArrayList();//右边的<>可以不写。1.8特性自己动推断。

        //2 测试共同方法
        //2.1 添加元素
        list.add("张楚岚");
        list.add("宝儿姐");
        list.add("徐三");
        System.out.println(list);//[张楚岚, 宝儿姐, 徐三]

       //list.clear();  //清空集合

        //2.2 contains(); 是否包含该元素,返回boolean类型
        System.out.println("contains: "+ list.contains("宝儿姐"));

        //2.3 isEmpty(); 判断集合中是否包含元素。
        System.out.println("isEmpty: "+ list.isEmpty());

        //3 测试独特方法List方法
        //add(index,e); 在指定位置添加元素。
        list.add(2,"徐四"); //索引元素就是输出顺序.
        System.out.println(list);//[张楚岚, 宝儿姐, 徐四, 徐三]

        //3.1 get()获取指定索引处元素。
        System.out.println("get(): "+list.get(1));

        //3.2 indexof();返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
        // lastindexof(); 最后一次出现的元素的索引。
        list.add("宝儿姐");//再次向集合中添加元素。为了测试indexof()
        System.out.println("indexof: "+list.indexOf("宝儿姐"));
        System.out.println("lastindexof: "+list.lastIndexOf("宝儿姐"));
        //3.3 remove(int index): 移除对应索引的元素。
        System.out.println("remove(): "+list.remove(0));//移除第一个索引元素
        System.out.println(list);

        //3.4 remove(object):移除一个出现的元素。
        System.out.println(list.remove("宝儿姐"));
        System.out.println(list);

        //3.5 set(index ,e):相当于修改操作,在指定位置修改元素
        System.out.println("set(): "+list.set(0,"张楚岚"));
        System.out.println(list);


        //3.6 sublist(fromindex toindex): 包含开始,不包含结尾,截取一个新的集合。
        List<String> list1 = list.subList(1, 2);
        list1.add("徐四");//向新集合中添加元素
        System.out.println(list1);//[徐三, 徐四]


        /*
         *集合间的操作,当两个集合不一样时,如list1 和list,
         */
        System.out.println(list);
        //System.out.println(list1.removeAll(list));//删除的是list
        System.out.println(list1.retainAll(list)); //是保留的意思list集合中元数。删除的是list1中的。 
        System.out.println(list1);
    }
}

  • 输出结果:

    [张楚岚, 宝儿姐, 徐三]
    contains: true
    isEmpty: false
    [张楚岚, 宝儿姐, 徐四, 徐三]
    get(): 宝儿姐
    indexof: 1
    lastindexof: 4
    remove(): 张楚岚
    [宝儿姐, 徐四, 徐三, 宝儿姐]
    true
    [徐四, 徐三, 宝儿姐]
    set(): 徐四
    [张楚岚, 徐三, 宝儿姐]
    [徐三, 徐四]
    [张楚岚, 徐三, 徐四, 宝儿姐]
    false
    [徐三, 徐四]
    

1.4.2 练习:迭代器测试

  1. 迭代器的使用。
  2. List迭代器很丰富因为有索引,你可以使用iterator() ,listIterator() ,也可以是用增强foreachfor循环都可以。
ublic class Test_List2 {
    public static void main(String[] args) {
        /*
            主要是测试迭代器使用,即遍历。
            foreach()
            for()
            iterator()
            listIterator()
            listIterator(int index)
         */
        List<String> list = new ArrayList();//右边的<>可以不写。1.8特性自己动推断。
        //1 添加元素
        list.add("张楚岚");
        list.add("宝儿姐");
        list.add("灵玉师兄");
        list.add("老天师");

        //1种遍历方式 for循环 步长就是 list.size()获取结合中的元素。
        for (int i=0;i<list.size();i++){
            String s = list.get(i);//集合名称.get()根据指定索引获取集合。
            System.out.println(s);
        }

        //2种,使用 foreach 增强循环 缺点:无法操作索引,只能从头到尾输出。
        //foreach(遍历数据类型 变量名称:集合)
        System.out.println("---------------------------华丽分割线2---------------------------");
        for (String s_resault:list) {
            System.out.println(s_resault);
        }
        System.out.println("---------------------------华丽分割线3---------------------------");
        //3种,使用collection中的遍历方式 iterator()
        Iterator<String> it = list.iterator();
        while (it.hasNext()){ //判断集合中是否还要下一个元素
            String next = it.next(); //获取下一个元素
            System.out.println(next);
        }
        System.out.println("---------------------------华丽分割线4---------------------------");
        //4种,使用自己的迭代器,listiterator(); 这个迭代器还有自己的方法可以(逆向操作:即反向输出)。
        ListIterator<String> it2 = list.listIterator();
        while (it2.hasNext()){
            String next = it2.next();
            System.out.println(next);
        }
        System.out.println("---------------------------反向操作---------------------------");
        //反向操作,一般情况下不用!
        while (it2.hasPrevious()){
            String previous = it2.previous();
            System.out.println(previous);
        }


        System.out.println("---------------------------华丽分割线5---------------------------");
        ListIterator<String> iterator = list.listIterator(2);//相当于从第二个索引开始
        while (iterator.hasNext()){
            String next = iterator.next();
            System.out.println(next);
        }

    }
}

输出结果:

张楚岚
宝儿姐
灵玉师兄
老天师
---------------------------华丽分割线2---------------------------
张楚岚
宝儿姐
灵玉师兄
老天师
---------------------------华丽分割线3---------------------------
张楚岚
宝儿姐
灵玉师兄
老天师
---------------------------华丽分割线4---------------------------
张楚岚
宝儿姐
灵玉师兄
老天师
---------------------------反向操作---------------------------
老天师
灵玉师兄
宝儿姐
张楚岚
---------------------------华丽分割线5---------------------------
灵玉师兄
老天师

2. ArrayList 实现类

2.1 概述

  1. java.util.ArrayList包下,底层是数据结构是 数组
    • 元素有序,有下标索引),可以重复
  2. 有集合的特点可以扩容,但是第一次初始化的时以 “0”的空数组
    • 当初次add()时,增加元素时,第一次扩容为10,然后每次以前一次的1.5倍扩容。(相当于一个懒加载模式)。
  3. ArrayList 因为底层是数组结构,
    • 特点: 查询快(因为有索引),相对来说 增加和删除效率低
      在这里插入图片描述

2.2 创建对象

  1. Api提供的创建对象的方式有3种,由于是实现类,可以直接创建对象。
1.ArrayList() ;  推荐第一种!
		          构造器创建对象。
2.ArrayList(Collection<? extends E> c); 
	          构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。 
3.ArrayList(int initialCapacity);
		       构造具有指定初始容量的空列表。  

2.3 练习:ArrayList()

  1. 虽然之前练习过,要注意程序由上到下执行,方法执行后会改变元素个数。
    • 重复的事情,认真做!
public class Test_ArrayList {
    public static void main(String[] args) {
        ArrayList<Integer> a = new ArrayList<>();
        a.add(1);
        a.add(2);
        a.add(4);
        a.add(5);
        System.out.println(a);

        //集合2
        ArrayList<Integer> a1 = new ArrayList<>();
        a1.add(100);
        a1.add(200);
        a1.add(300);

        //测试arraylist方法,大部分都见过。
        a.add(2,3); //在索引2的位置插一个3。
        System.out.println(a);

        //contains():是否包含此元素
        System.out.println("contains: "+a.contains(1));
        //clone():浅拷贝返回一个Objct的数组。相当于拷贝了引用地址值。
        // 使用时需要强制转换(ArrayList<Interger>)clone;
        Object clone = a.clone();
        System.out.println("clone: "+clone);

        //get():通过索引获取元素
        System.out.println("get(): "+a.get(2));

        //indexof()和lastindexof();第一个出现和最后一个出现
        a.add(1);//想集合中添加元素 1。为了测试
        System.out.println("indexof(): "+a.indexOf(1));
        System.out.println("lastindexof(): "+a.lastIndexOf(1));

        //isEmpty();判断集合是否包含元素
        System.out.println("isEmpty(): "+a1.isEmpty());

        //remove();删除集合指定的元素有两种情况,可以根据索引删除,也根据元素删除;
        System.out.println("remove(): "+a.remove(1)); //返回索引值
        System.out.println("remove(object o): "+a.remove(1));//返回索引值

        //size():返回集合元素个数
        System.out.println("size() :"+a.size());
        //get():根据下标获取元素
        System.out.println("get() : "+a.get(0));

        System.out.println("---------------------华丽分割线---------------------");



        /*集合之间的操作*/
        //addAll(collection<>); 相当于将(a1)集合中的元素按照位置插入到a集合中。
        //addAll(index collection<>); 相当于将(a1)集合中的元素按照位置插入到a集合中。
        System.out.println(a.addAll(a1));
        //System.out.println("addAll(): "+a);
        System.out.println(a.addAll(2, a1));
        System.out.println("addAll(): "+a);

        //a1.clear(); //清除集合中的元素。

        System.out.println("---------------------华丽分割线---------------------");


        /*
               遍历集合ArrayList();
         */

        //1.for循环
        for (int i=0;i<a.size();i++){ //a.size():相当于集合步长
            Integer i_resault = a.get(i); //get()根据下标获取元素。
            System.out.println(i_resault);
        }

        System.out.println("---------------------华丽分割线---------------------");
        //2.种遍历方式,用自己的迭代器iterator()
        Iterator<Integer> iterator = a.iterator();
        while (iterator.hasNext()){
            Integer next = iterator.next();
            System.out.println(next);
        }

    }
}
  • 输出结果:

    [1, 2, 4, 5]
    [1, 2, 3, 4, 5]
    contains: true
    clone: [1, 2, 3, 4, 5]
    get(): 3
    indexof(): 0
    lastindexof(): 5
    isEmpty(): false
    remove(): 2
    remove(object o): 3
    size()4
    get() : 1
    ---------------------华丽分割线---------------------
    true
    true
    addAll(): [1, 4, 100, 200, 300, 5, 1, 100, 200, 300]
    ---------------------华丽分割线---------------------
    1
    4
    100
    200
    300
    5
    1
    100
    200
    300
    ---------------------华丽分割线---------------------
    1
    4
    100
    200
    300
    5
    1
    100
    200
    300
    

3. LinkedList 实现类

3.1 概述

  1. 底层不同于ArrayList数组结构LinkedList底层是 链表结构,
    • 而且是 双向链表,有序,逻辑索引,不不同于ArrayList 下标索引,(这句话怎么理解?)。
  2. 所谓的链表:如生活中的自行车链条,一个 node(节点) 连接另一个节点。
    • 双向链表,LinkedList中维护了两个属性firstlast分别指向 首节点和尾结点。
  3. 听起来比较懵咱们走一波小图画!

在这里插入图片描述

  1. 上图总结:
    • Linkedlist底层是双链表结构,每一个连接点称为Node(节点),封装着三个属性:分别是存储元素,上一个节点的地址值,下一个节点的地址值。
    • 其实Linkedlist不同于Arraylist那样的索引,LinkedList 可以理解为 “逻辑索引”每一次查询相当于一次for循环),每一次查询,都是从头开始一直查询到尾。
    • 首节点和尾节点,会连接不同于其他节点,二者很近。所以针对首尾操作提供了大量的api。
    • 这样的特殊结构就相对于ArrayList来说,特点: 查询慢,插入,删除快。
  2. 源码分析。
    • Node节点是一个类
	private static class Node<E> {
	    E item;	//存储对象
	    Node<E> next;	// 当前节点的next指针,指向下一个next
	    Node<E> prev;	// 当前节点的prev指针,指向上一个、prev
	
	    Node(Node<E> prev, E element, Node<E> next) {
	        this.item = element;
	        this.next = next;
	        this.prev = prev;
	    }
	}

 transient int size = 0; //初始化大小

    /**
     * Pointer to first node.
     * Invariant: (first == null && last == null) ||
     *            (first.prev == null && first.item != null)
     */
    transient Node<E> first; //告诉你哪个是首节点,并指向首节点

    /**
     * Pointer to last node.
     * Invariant: (first == null && last == null) ||
     *            (last.next == null && last.item != null)
     */
    transient Node<E> last; //指向尾节点,告诉你哪个是尾节点

    /**
     * Constructs an empty list.
     */
    public LinkedList() {
    }

3.2 创建对象

  1. LinkedList创建对象的方式:

    • 通过构造方法。
    	new LinkedList() ; 
    		通过构造函数,直接new 创建对象。
    

3.3 常用方法介绍

  1. LinkedList也实现了List接口,那么List有的方法,它也会,但是也有自己独特的方法。
  2. LinkedList针对首尾元素的 添加和删除 ,提供了很多套API的方法,
    • 只需要记住一套 使用即可。
常用方法作用
void add(int index, E element)在此列表中的指定位置插入指定的元素。
void addFirst(E e)在该列表开头插入指定的元素。
void addLast(E e)将指定的元素追加到此列表的末尾
E element()检索但不删除此列表的头(第一个元素)。
E get(int index)返回此列表中指定位置的元素。
E getFirst()返回此列表中的第一个元素。
E getLast()返回此列表中的最后一个元素。
E removeFirst()从此列表中删除并返回第一个元素。
E removeLast()从此列表中删除并返回最后一个元素。
boolean offer(E e)将指定的元素添加为此列表的尾部(最后一个元素)。
boolean offerFirst(E e)在此列表的前面插入指定的元素。
boolean offerLast(E e)在该列表的末尾插入指定的元素。
E peek()检索但不删除此列表的头(第一个元素)。
E peekFirst()检索但不删除此列表的第一个元素,如果此列表为空,则返回 null 。
E peekLast()检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null 。
E poll()检索并删除此列表的头(第一个元素)。
E pollFirst()检索并删除此列表的第一个元素,如果此列表为空,则返回 null 。
E pollLast()检索并删除此列表的最后一个元素,如果此列表为空,则返回 null 。

3.4 练习:LinkedList()

  1. 主要针对首尾添加元素,提供了多套添加首尾元素的方法,只需要掌握一套即可。其他了解。
    • 为什么没有索引还提供了一个get(int index)方法查询。
public class Test_LinkedList {
    public static void main(String[] args) {
        //1.创建对象
        LinkedList<String> linkedList = new LinkedList();
        linkedList.add("钢铁侠");
        linkedList.add("雷神");
        linkedList.add("鹰眼");
        linkedList.add("绿巨人");

        System.out.println(linkedList);//[钢铁侠, 雷神, 鹰眼, 绿巨人],从添加输出来看,集合有序。

        //2.测试LinkedList方法

        //2.1 void add(int index, E element):根据索引添加指定元数。
        linkedList.add(2,"美国队长");//向指定索引处,添加元素。
        System.out.println(linkedList.get(3));; //根据索引获取指定元数。
        System.out.println(linkedList);

        //2.2 addFirst()和 addLast(),在头插入元素和在尾插入元素
        linkedList.addFirst("冬兵");//插入首元素
        linkedList.addLast("黑豹");// 插入尾元素
        System.out.println(linkedList);

        //2.3 getFirst()和 getLast(),获取首尾元素
        System.out.println(linkedList.getFirst());
        System.out.println(linkedList.getLast());

        //2.4 E element();
        System.out.println(linkedList.element());//也是返回第一个元素,底层调用getFirst();

        //2,5 removeFirst()和 removeLast() 移除第一个和最后一个元素
        System.out.println(linkedList.removeFirst());//返回移除元素
        System.out.println(linkedList.removeLast());// 返回移除元素
        System.out.println(linkedList);


        System.out.println("-----------------华丽的分割线------------------");

        // 3测试其他方法
        LinkedList<String> linkedList2 = new LinkedList();
        linkedList2.add("大娃");
        linkedList2.add("二娃");
        linkedList2.add("三娃");
        //3.1 查询方法 peek()
        System.out.println(linkedList2.peek());// 检索第一个
        System.out.println(linkedList2.peekFirst());
        System.out.println(linkedList2.peekLast());


        //3.2 添加方法 offer()
        System.out.println(linkedList2.offer("金刚葫芦娃"));//末尾插入元素
        System.out.println(linkedList2.offerFirst("四娃"));
        System.out.println(linkedList2.offer("五娃"));
        System.out.println(linkedList2);


        //3.3 移除方法 poll()
        System.out.println(linkedList2.poll());//移除第一个元素
        System.out.println(linkedList2.pollFirst());//移除第一个元素
        System.out.println(linkedList2.pollLast());//移除第最后一个元素
        System.out.println(linkedList2);

        System.out.println("-----------------华丽的分割线------------------");
        //4.遍历使用 foreach 效率高!
        for (String slist:linkedList2) {
            System.out.println(slist);
        }


        //5.也可以用iterator迭代遍历
        Iterator<String> iterator = linkedList2.iterator();
        while (iterator.hasNext()){
            String next = iterator.next();
            System.out.println(next);
        }

    }
}

输出结果:

[钢铁侠, 雷神, 鹰眼, 绿巨人]
鹰眼
[钢铁侠, 雷神, 美国队长, 鹰眼, 绿巨人]
[冬兵, 钢铁侠, 雷神, 美国队长, 鹰眼, 绿巨人, 黑豹]
冬兵
黑豹
冬兵
冬兵
黑豹
[钢铁侠, 雷神, 美国队长, 鹰眼, 绿巨人]
-----------------华丽的分割线------------------
大娃
大娃
三娃
true
true
true
[四娃, 大娃, 二娃, 三娃, 金刚葫芦娃, 五娃]
四娃
大娃
五娃
[二娃, 三娃, 金刚葫芦娃]
-----------------华丽的分割线------------------
二娃
三娃
金刚葫芦娃
二娃
三娃
金刚葫芦娃

3.5 知识点: 自己思考下

  • 自己思考并总结,ArrayList和LinkedList区别:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吴琼老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值