List集合和数据结构

Day07

今日内容

  • 集合的概述和集合继承体系
  • Collection集合
  • List集合
  • ArrayList集合
  • LinkedList集合
  • 数据结构
  • 源码【不建议过深的去研究】

今日目标

  • 集合继承体系【了解】
  • Collection集合特点及常用API【应用、理解】
  • List集合特点及常用API【应用、理解】
  • ArrayList集合【应用、理解】
  • LinkedList集合【应用、理解】
  • 数据结构【理解】

01-集合和数组的对比

  • 问题:ArrayList和数组的区别?
1.大小(长度):
数组:长度不可变
集合:可变的(自动扩容)

2.定义(存储的数据类型):
数组:基本数据类型和引用数据类型
集合:引用数据类型(包括基本数据类型的包装类)

02-集合的体系结构

  • 问题:集合分为哪两大类
Collection	单列集合
Map	双列集合
  • 问题:ArrayList属于哪一类集合?
Collection 单列
  • 体系结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E08ONwyz-1634922812639)(day07随堂笔记.assets/集合体系.png)]

03-Collection常见成员方法

- 添加元素
	boolean add(E e)	添加成功返回true 失败返回false
- 从集合中移除指定元素
	boolean remove(Object o)	删除成功返回true	失败返回false
- 根据条件进行删除
	default boolean removeIf(Predicate<? super E> filter)	删除成功返回true	失败返回false
- 清空集合
	void clear()	
- 判断集合中是否存在指定的元素
	boolean contains(Object o)	存在返回true	不存在返回false
- 判断集合是否为空		空代表没有数据 长度是0
	boolean isEmpty()	为空返回true	不为空返回false
- 集合的长度,集合元素的个数
	int size()	
  • 代码
public class MyCollectonDemo2 {
    public static void main(String[] args) {
        Collection<String> collection = new ArrayList<>();
//        boolean add(E e)		添加元素
        collection.add("aaa");
        collection.add("bbb");
        collection.add("ccc");
        collection.add("dddd");
        //System.out.println(collection);
        //method1(collection);
        //method2(collection);
        //method3(collection);
        //method4(collection);
        //method5(collection);
        //method6(collection);


    }

    private static void method6(Collection<String> collection) {
        //        int size()			集合的长度,也就是集合中元素的个数
        int size = collection.size();
        System.out.println(size);
    }

    private static void method5(Collection<String> collection) {
        //        boolean isEmpty()		判断集合是否为空
        collection.clear();
        boolean result = collection.isEmpty();
        System.out.println(result);
    }

    private static void method4(Collection<String> collection) {
        //        boolean contains(Object o)	判断集合中是否存在指定的元素
        boolean result = collection.contains("a");
        System.out.println(result);


        boolean result2 = collection.contains("aaa");
        System.out.println(result2);
    }

    private static void method3(Collection<String> collection) {
        //        void clear()			清空集合
        //就是将集合中所有的元素全部删除.
        collection.clear();
        System.out.println(collection);
    }

    private static void method2(Collection<String> collection) {
        //        boolean removeif(Object o)	根据条件进行删除
        //removeif底层会遍历集合,得到集合中的每一个元素
        //s依次表示集合中的每一个元素
        //就会把这每一个元素都到lambda表达式中去判断一下
        //如果返回的是true,则删除
        //如果返回的是false,则保留不删除.


        //boolean test(String t);
        collection.removeIf(
                (String s)->{
                    return s.length() == 3;
                }

        );
        System.out.println(collection);
    }

    private static void method1(Collection<String> collection) {
        //        boolean remove(Object o)	    从集合中移除指定的元素
        //如果删除成功了,则返回true
        //如果删除失败了,则返回false
        boolean result1 = collection.remove("aaa");
        boolean result2 = collection.remove("ddd");
        System.out.println(result1);
        System.out.println(result2);
        System.out.println(collection);
    }
}
  • 需要注意的方法
- 扩展
	contains	依赖存储对象的equals方法 
- 匿名内部类或者lambda表达式
	removeIf
- 判断的是size()是否等于0
	isEmpty()

04-Collection迭代器基本使用

  • 问题:迭代器的作用是什么?
- 遍历集合
  • 问题:迭代器的两个成员方法的【作用】是什么?

判断当前索引位置是否有元素
boolean hasNext()	

1.取出当前索引的元素
2.向后移了一位
E next()
  • 迭代器的使用,代码
Collection<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("e");
Iterator<String> it = list.iterator();
while(it.hasNext()){
    String s = it.next();
    System.out.println(s);
}

05-Collection迭代器原理分析

  • 分析
// 获取一个迭代器对象,初识指向集合0索引处
Iterator<String> it = list.iterator();
// 判断当前位置是否有元素可以被取出
it.hasnext()
// 取出当前位置的元素
// 将迭代器对象移向下一个索引位置
it.next()
  • debug
关注Iterator中【cursor】变量

06-Collection迭代器删除方法

  • 理解for循环中删除两个相邻的元素,不能删除成功

根本原因:ArrayList可变,当删除一个元素后,后面的元素会向前移动补齐

// 现象:相邻两个元素 后一个删除不成功
// 原因:集合的长度变化了(缩短)
// 解决办法:每次删除成功i--
// 			迭代器的remove()


- 断点debug调试
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");

for (int i = 0; i < list.size(); i++) {
    String s = list.get(i);		// 断点位置:关注变量i、list.size()、s
    if("b".equals(s)){
    	list.remove(i);
    }
}
    
  • 迭代器的删除方法不会出现上述问题

根本原因 迭代器remove方法,迭代器中的cursor变量, 执行了 cursor–;操作

- debug:

ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("b");
list.add("c");
list.add("d");

Iterator<String> it = list.iterator();
while(it.hasNext()){
  String s = it.next();	// 断点位置:关注变量s、it中的cursor
  if("b".equals(s)){
      it.remove();
  }
}
System.out.println(list);

07-增强for基本格式

  • 问题:增强for底层使用什么实现的遍历?
迭代器
  • 问题:集合使用增强for,需要实现什么接口?单列集合(Collection)、双列集合(Map)谁实现了这个接口?
Iterable
单列集合实现了这个接口
  • 问题:哪些类型可以使用增强for?
数组
所有的单列集合
  • 格式
for(元素的数据类型 变量名 : 数组或Collection集合){
	//使用变量,变量就代表元素
}

for(Integer i : arrayList){
	System.out.println(i);
}
  • 示例
// 集合
ArrayList<String> arrayList = new ArrayList<>();
for (String str : arrayList) {
    System.out.println(str);
}

// 数组
int[] arr = new int[5];
for (int i : arr) {
    System.out.println(i);
}

08-增强for注意点

  • 增强for中的变量理解
- 对比普通for循环理解 增强for循环中的变量

- 所谓的第三方变量
for(Integer i : arrayList){
    i = 10;
    System.out.println(i);
}

for (int i = 0; i < arrayList.size(); i++) {
    Integer intt = arrayList.get(i);
    intt = 10;
}
  • 问题:三种遍历方式使用场景是什么?
- 普通for 需要操作索引的时候
- 增强for 仅仅遍历用
- 迭代器 遍历时删除元素(可以避免:相邻两个元素 后一个删除不成功)

09-Collection-练习

  • 两种方式遍历Collection集合
思路:
	- 定义学生类
	- 创建Collection集合对象
	- 创建学生对象
	- 把学生添加到集合
	- 迭代器遍历集合
	- 增强for遍历集合

10-List-概述和基本使用

  • 问题:List集合有什么特点?
1.有序:存取有序
2.有索引:通过索引操作元素
3.可重复:存储的元素可以重复
  • 基本使用(Collection相关API)、遍历方式

11-List-特有方法

根据索引操作

void add(int index, E element) 在集合中指定位置插入元素,原来位置的元素向后移动一位
E remove(int index)	删除指定索引处的元素,返回被删除的元素,后面的元素向前补齐
boolean remove(Object o)	删除成功返回true	失败返回false	
E set(int index, E element) 修改指定索引处的元素,返回被修改的元素
E get(int index)	返回指定索引处的元素

12-数据结构-栈和队列

  • 栈特点
像弹夹,数据先进后出
应用:
- 栈内存
  • 队列特点
像排队,数据先进先出
应用:
- ArrayBlockingQueue	多线程当中用到的队列

13-数据结构-数组和链表

  • ArrayList中处理数组(可变数组)的特点
可变数组:代码实现的

- 查询:通过数组的地址,找数组的索引
	- 查询快
- 添加:中间插入数据,后面其他数据依次向后移动
- 删除:删除中间的数据,后面其他数据依次向前移动补齐
	- 增删慢
  • 链表的特点
- 增加、删除:只要换节点的地址值就行了
	- 增删快,相对数组
- 查询:从头节点依次向后找
	- 查询慢,相对数组
	
- 单向链表:一个节点记录下一个节点地址值
- 双向链表:一个节点记录前后节点的地址值,查询时距离头尾哪边近,就从哪边找

14-ArrayList-源码解析

- debug
// 1.ArrayList<String> list = new ArrayList<>();创建一个长度为0的空数组
// 2.每次扩容容量为原容量的1.5倍
public class Test8 {
    public static void main(String[] args) {
        //
        ArrayList<String> list = new ArrayList<>();
       /*
       1.elementData底层数组的变量名
       2.Object[] 空数组 {}
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }
        */

        list.add("aaa");
/*

        public boolean add(E e) {
            modCount++;
            1.e 要添加的 aaa
            2.elementData 底层数组
            3.size 当前操作的索引:0
            add(e, elementData, size);
            return true;
        }
        */

/*
        private void add(E e, Object[] elementData, int s) { 第一个参数:aaa 第二个参数:{} 第三个参数:0
            // 什么情况下扩容:当前指向的索引值等于数组的长度 装满了
            if (s == elementData.length)
                // 调用扩容方法 grow() 返回一个扩容后的数组
                // elementData底层数组 = 扩容后的数组
                elementData = grow();
            // 把当前要添加的值 赋值到0索引的位置
            elementData[s] = e;
            // size = 0 + 1 指向了1索引位置
            size = s + 1;
        }
        */

/*

        private Object[] grow() {
            // 调用了一个有参的grow方法 并且传的值是size + 1
            return grow(size + 1);
        }
*/

/*

        private Object[] grow(int minCapacity) { 参数:1
         Arrays.copyOf 复制原数组的数据到一个长度为10的数组中,返回给  elementData 底层数组

            return elementData = Arrays.copyOf(elementData,
                    newCapacity(minCapacity));
        }
*/
/*

        private int newCapacity(int minCapacity) { 参数minCapacity: 1
            // overflow-conscious code
            1.oldCapacity旧容量:0
            int oldCapacity = elementData.length;
            2.newCapacity新容量= 旧容量 * 1.5       目前的值是0
            int newCapacity = oldCapacity + (oldCapacity >> 1); (n + n / 2)

            3.判断 0 - 1 是不是小于等于0
            if (newCapacity - minCapacity <= 0) {
                4.{} = {}
                if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                    5.去两个值得最大值
                    DEFAULT_CAPACITY:10
                    minCapacity:10
                    return Math.max(DEFAULT_CAPACITY, minCapacity);
                if (minCapacity < 0) // overflow
                    throw new OutOfMemoryError();
                return minCapacity;
            }
            return (newCapacity - MAX_ARRAY_SIZE <= 0)
                    ? newCapacity
                    : hugeCapacity(minCapacity);
        }*/

    }
}

15-LinkedList-基本运用

  • 基本使用(Collection相关API)、遍历方式

16-LinkedList-特有功能

public void addFirst(E e)	在列表开头插入指定的元素
public void addLast(E e)	将指定的元素追加到此列表的末尾
public E getFirst()	返回此列表的第一个元素
public E getLast()	返回此列表的最后一个元素
public E removeFirst()	从此列表删除并返回第一个元素
public E removeLast()	从此列表删除并返回最后一个元素

- 当集合中只有一个元素的时候,getFirst 和 getLast 获取的是一样的
- 当集合中没有元素的时候 removeFirst 和 removeLast 会报异常:NoSuchElementException

17-LinkedList-源码解析

-debug
public class Test10 {
    public static void main(String[] args) {
        /*public class LinkedList{
            // 头结点
            Node first = null;
            // 尾节点
            Node last = null;
        }*/

/*
        Node内部类
        private static class Node<E> {

            E item;  节点中存的值
            Node<E> next;  下一个节点的地址值
            Node<E> prev;   上一个节点的地址值

            构造方法
            Node(Node<E> prev, E element, Node<E> next) { 上一个,值,下一个
                this.item = element;
                this.next = next;
                this.prev = prev;
            }
        }
*/

/*
        从尾部追加
        void linkLast(E e) {
            1.尾节点记录到 l 变量中
            final Node<E> l = last;
            2.创建一个节点 传参:尾节点,值,null
            3.这个节点的
               上一个: 当前的尾节点地址值
               值: 要添加的值
               下一个: null
            final Node<E> newNode = new Node<>(l, e, null);
            4.把新的节点变成了尾节点
            last = newNode;
            5.如果第一次添加,尾部应该是null
            if (l == null)
                first = newNode;
            6.否则让节点的(下一个)指向新节点
            else
                l.next = newNode;
            size++;
            modCount++;
        }*/


        LinkedList<String> list = new LinkedList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRyi2waE-1634922812641)(day07随堂笔记.assets/链表.png)]

  • 扩展
// 把一个集合中的所有数据添加到另一个集合当中
// addAll(Collection collection)

ArrayList<String> list1 = new ArrayList<>();
list1.add("aaa");
list1.add("bbb");

LinkedList<String> list2 = new LinkedList<>();
list2.add("qqq");
list2.add("ttt");

list1.addAll(list2);

System.out.println(list1);




// 用一个集合里面的数据创建另一个集合 
LinkedList<String> list = new LinkedList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");

ArrayList<String> arrayList = new ArrayList<>(list);
System.out.println(arrayList);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值