JAVA进阶--Collection集合、常见数据结构、泛型深入--2022年9月2日
第一节 集合概述
1、数组和集合的元素存储的个数问题
数组定义后类型确定,长度固定
集合类型可以不固定,大小是可变的
2、数组和集合存储元素的类型问题
数组可以存储基本类型和引用类型的数据
集合只能存储引用数据类型的数据
3、数组和集合适合的场景
数组适合做数据个数和类型确定的场景
集合适合做数据个数不确定,且要做增删元素的场景
第二节 Collection集合体系
1、集合体系:Collection单列集合家族、Map双列集合家族
2、Collextion单列集合家族
ps:有序的意思是先添加的元素在前面,后添加的元素在后面,不是排序的意思。
3、集合的代表是?
Collection集合
4、Collection集合分了哪2大常用的集合体系?
List系列集合:添加的元素是有序、可重复、有索引
Set系列集合:添加的元素是无序、不重复、无索引
5、如何约定集合存储数据的类型,需要注意什么?
集合支持泛型
集合和泛型不支持基本类型的数据,只支持引用类型的数据
6、Collection常用API
package com.maofugui.collection; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; /** 目标:Collection集合的常用API. Collection是集合的祖宗类,它的功能是全部集合都可以继承使用的,所以要学习它。 Collection API如下: - public boolean add(E e): 把给定的对象添加到当前集合中 。 - public void clear() :清空集合中所有的元素。 - public boolean remove(E e): 把给定的对象在当前集合中删除。 - public boolean contains(Object obj): 判断当前集合中是否包含给定的对象。 - public boolean isEmpty(): 判断当前集合是否为空。 - public int size(): 返回集合中元素的个数。 - public Object[] toArray(): 把集合中的元素,存储到数组中。 小结: 记住以上API。 */ public class CollectionDemo { public static void main(String[] args) { // HashSet:添加的元素是无序,不重复,无索引。 Collection<String> c = new ArrayList<>(); // 1.添加元素, 添加成功返回true。 c.add("Java"); c.add("HTML"); System.out.println(c.add("HTML")); c.add("MySQL"); c.add("Java"); System.out.println(c.add("黑马")); System.out.println(c); // [Java, HTML, HTML, MySQL, Java, 黑马] // 2.清空集合的元素。 // c.clear(); // System.out.println(c); // 3.判断集合是否为空 是空返回true,反之。 // System.out.println(c.isEmpty()); // 4.获取集合的大小。 System.out.println(c.size()); // 5.判断集合中是否包含某个元素。 System.out.println(c.contains("Java")); // true System.out.println(c.contains("java")); // false System.out.println(c.contains("黑马")); // true // 6.删除某个元素:如果有多个重复元素默认删除前面的第一个! System.out.println(c.remove("java")); // false System.out.println(c); System.out.println(c.remove("Java")); // true System.out.println(c); // 7.把集合转换成数组 [HTML, HTML, MySQL, Java, 黑马] Object[] arrs = c.toArray(); System.out.println("数组:" + Arrays.toString(arrs)); System.out.println("----------------------拓展----------------------"); Collection<String> c1 = new ArrayList<>(); c1.add("java1"); c1.add("java2"); Collection<String> c2 = new ArrayList<>(); c2.add("赵敏"); c2.add("殷素素"); // addAll把c2集合的元素全部倒入到c1中去。 c1.addAll(c2); System.out.println(c1); System.out.println(c2); } }
7、Collection集合的遍历方式
a、使用迭代器遍历
迭代器默认位置在哪里
Iterator<E>itarator():得到迭代器对象,默认指向当前的集合索引0
迭代器如果取元素索引越界会出现什么问题
会出现NoSuchElementException异常
package com.maofugui.collection; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** 目标:Collection集合的遍历方式。 什么是遍历? 为什么开发中要遍历? 遍历就是一个一个的把容器中的元素访问一遍。 开发中经常要统计元素的总和,找最值,找出某个数据然后干掉等等业务都需要遍历。 Collection集合的遍历方式是全部集合都可以直接使用的,所以我们学习它。 Collection集合的遍历方式有三种: (1)迭代器。 (2)foreach(增强for循环)。 (3)JDK 1.8开始之后的新技术Lambda表达式(了解) a.迭代器遍历集合。 -- 方法: public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的 boolean hasNext():判断是否有下一个元素,有返回true ,反之。 E next():获取下一个元素值! --流程: 1.先获取当前集合的迭代器 Iterator<String> it = lists.iterator(); 2.定义一个while循环,问一次取一次。 通过it.hasNext()询问是否有下一个元素,有就通过 it.next()取出下一个元素。 小结: 记住代码。 */ public class CollectionDemo2 { public static void main(String[] args) { ArrayList<String> lists = new ArrayList<>(); lists.add("赵敏"); lists.add("小昭"); lists.add("素素"); lists.add("灭绝"); System.out.println(lists); // [赵敏, 小昭, 素素, 灭绝] // it // 1、得到当前集合的迭代器对象。 Iterator<String> it = lists.iterator(); // String ele = it.next(); // System.out.println(ele); // System.out.println(it.next()); // System.out.println(it.next()); // System.out.println(it.next()); // System.out.println(it.next()); // NoSuchElementException 出现无此元素异常的错误 // 2、定义while循环 while (it.hasNext()){//判断当前指针的元素是否为空 String ele = it.next();//next()是先取元素,再把指针移到下一位 System.out.println(ele); } System.out.println("-----------------------------"); } }
b、foreach遍历/增强for循环
增强for可以遍历哪些容器
既可以遍历集合也可以遍历数组
增强for的关键是记住它的遍历格式
for(元素数据类型 变量名:数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}
package com.maofugui.collection; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; /** 目标:Collection集合的遍历方式。 什么是遍历? 为什么开发中要遍历? 遍历就是一个一个的把容器中的元素访问一遍。 开发中经常要统计元素的总和,找最值,找出某个数据然后干掉等等业务都需要遍历。 Collection集合的遍历方式是全部集合都可以直接使用的,所以我们学习它。 Collection集合的遍历方式有三种: (1)迭代器。 (2)foreach(增强for循环)。 (3)JDK 1.8开始之后的新技术Lambda表达式。 b.foreach(增强for循环)遍历集合。 foreach是一种遍历形式,可以遍历集合或者数组。 foreach遍历集合实际上是迭代器遍历集合的简化写法。 foreach遍历的关键是记住格式: for(被遍历集合或者数组中元素的类型 变量名称 : 被遍历集合或者数组){ } */ public class CollectionDemo3 { public static void main(String[] args) { Collection<String> lists = new ArrayList<>(); lists.add("赵敏"); lists.add("小昭"); lists.add("殷素素"); lists.add("周芷若"); System.out.println(lists); // [赵敏, 小昭, 殷素素, 周芷若] // ele for (String ele : lists) { System.out.println(ele); } System.out.println("------------------"); double[] scores = {100, 99.5 , 59.5}; for (double score : scores) { System.out.println(score); // if(score == 59.5){ // score = 100.0; // 修改无意义,不会影响数组的元素值。 // } } System.out.println(Arrays.toString(scores)); } }
c、Lambda表达式
8、Collection集合存储自定义类型的对象,存储的是元素对象的地址
第三节 常见数据结构
1、栈:后进先出,先进后出
数据进入栈模型的过程叫做:压栈/进栈
数据离开栈模型的过程叫做:弹栈/出栈
2、队列:先进先出,后进后出
数据从后端进入队列模型的过程称为:入队列
数据从前端离开队列模型的过程称为:出队列
3、数组:元素在内存中是连续存储的
4、链表:链表中的元素在内存中是不连续存储的
=================================================================================
=====================================================================================================
5、二叉树、二叉查找树
=================================================================================================================================
=====================================================================================================================
普通二叉树没有规律,二叉查找树有规律
==============================================================================================================
6、平衡二叉树
有时候数据进来就是有顺序的,那存放在二叉树里就会变成左边的样子,变成链表,平衡二叉树可以解决这个问题
===================================================================================================================
=========================================================================================================
=========================================================================================================
7、红黑树
=========================================================================================================
=========================================================================================================
8、各种数据结构的特点和作用是什么样的
队列:先进先出,后进后出
栈:先进后出,后进先出
数组:内存连续区域,查询快(根据索引定位),增删慢
链表:元素是游离的,查询慢,首尾操作极快
二叉树:永远只有一个根节点,每个节点不超过2个子节点的树
查找二叉树:小的左边,大的右边,但是可能树很高,查询性能变差
平衡查找二叉树:让树的高度差不大于1,增删改查都提高了
红黑树:就是基于红黑规则实现了自平衡的排序二叉树
第四节 List集合
1、List系列集合特点
ArrayList、LinekdList :有序,可重复,有索引。
有序:存储和取出的元素顺序一致
有索引:可以通过索引操作元素
可重复:存储的元素可以重复
2、List集合特有方法
package com.itheima.d5_collection_list; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; /** 目标:ArrayList集合。 Collection集合的体系 Collection<E>(接口) / \ Set<E>(接口) List<E>(接口) / \ / \ \ HashSet<E>(实现类) TreeSet<E>(实现类) LinkedList<E>(实现类) Vector(线程安全) ArrayList<E>(实现类) / LinkedHashSet<E>(实现类) Collection集合体系的特点: Set系列集合: 添加的元素,是无序,不重复,无索引的。 -- HashSet:添加的元素,是无序,不重复,无索引的。 -- LinkedHashSet:添加的元素,是有序,不重复,无索引的。 List系列集合:添加的元素,是有序,可重复,有索引的。 -- LinkedList: 添加的元素,是有序,可重复,有索引的。 -- ArrayList: 添加的元素,是有序,可重复,有索引的。 -- Vector 是线程安全的,速度慢,工作中很少使用。 1、List集合继承了Collection集合的全部功能,"同时因为List系列集合有索引", 2、因为List集合多了索引,所以多了很多按照索引操作元素的功能: 3、ArrayList实现类集合底层基于数组存储数据的,查询快,增删慢! - public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。 - public E get(int index):返回集合中指定位置的元素。 - public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。 - public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回更新前的元素值。 小结: ArrayList集合的底层是基于数组存储数据。查询快,增删慢!(相对的) */ public class ListDemo01 { public static void main(String[] args) { // 1.创建一个ArrayList集合对象: // List:有序,可重复,有索引的。 ArrayList<String> list = new ArrayList<>(); // 一行经典代码! list.add("Java"); list.add("Java"); list.add("HTML"); list.add("HTML"); list.add("MySQL"); list.add("MySQL"); // 2.在某个索引位置插入元素。 list.add(2, "黑马"); System.out.println(list); // 3.根据索引删除元素,返回被删除元素 System.out.println(list.remove(1)); System.out.println(list); // 4.根据索引获取元素:public E get(int index):返回集合中指定位置的元素。 System.out.println(list.get(1)); // 5.修改索引位置处的元素: public E set(int index, E element) System.out.println(list.set(1, "传智教育")); System.out.println(list); } }
3、List的实现类的底层原理
ArrayList底层是基于数组实现的,根据查询元素快、增删相对慢
LinkedList底层基于双链表实现的,查询元素慢,增删收尾元素是非常快的
4、List集合的遍历方式有几种
迭代器
foreach循环/增强for循环
Lambda表达式
for循环(因为List集合存在索引)
package com.itheima.d5_collection_list; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** 拓展:List系列集合的遍历方式有:4种。 List系列集合多了索引,所以多了一种按照索引遍历集合的for循环。 List遍历方式: (1)for循环。(独有的,因为List有索引)。 (2)迭代器。 (3)foreach。 (4)JDK 1.8新技术。 */ public class ListDemo02 { public static void main(String[] args) { List<String> lists = new ArrayList<>(); lists.add("java1"); lists.add("java2"); lists.add("java3"); /** (1)for循环。 */ System.out.println("-----------------------"); for (int i = 0; i < lists.size(); i++) { String ele = lists.get(i); System.out.println(ele); } /** (2)迭代器。 */ System.out.println("-----------------------"); Iterator<String> it = lists.iterator(); while (it.hasNext()){ String ele = it.next(); System.out.println(ele); } /** (3)foreach */ System.out.println("-----------------------"); for (String ele : lists) { System.out.println(ele); } /** (4)JDK 1.8开始之后的Lambda表达式 */ System.out.println("-----------------------"); lists.forEach(s -> { System.out.println(s); }); } }
5、ArrayList集合的底层原理
存满后,每次扩容到1.5倍
其余的看视频
6、LinkedList集合的底层原理
package com.itheima.d5_collection_list; import java.util.LinkedList; import java.util.List; /** 目标:LinkedList集合。 Collection集合的体系: Collection<E>(接口) / \ Set<E>(接口) List<E>(接口) / / \ \ HashSet<E>(实现类) LinkedList<E>(实现类) Vector(实现类) ArrayList<E>(实现类) / LinkedHashSet<E>(实现类) Collection集合体系的特点: Set系列集合: 添加的元素,是无序,不重复,无索引的。 -- HashSet:添加的元素,是无序,不重复,无索引的。 -- LinkedHashSet:添加的元素,是有序,不重复,无索引的。 List系列集合:添加的元素,是有序,可重复,有索引的。 -- LinkedList: 添加的元素,是有序,可重复,有索引的。 -- Vector: 添加的元素,是有序,可重复,有索引的。线程安全(淘汰了) -- ArrayList: 添加的元素,是有序,可重复,有索引的。 LinkedList也是List的实现类:底层是基于双链表的,增删比较快,查询慢!! LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的 所以LinkedList除了拥有List集合的全部功能还多了很多操作首尾元素的特殊功能: - public void addFirst(E e):将指定元素插入此列表的开头。 - public void addLast(E e):将指定元素添加到此列表的结尾。 - public E getFirst():返回此列表的第一个元素。 - public E getLast():返回此列表的最后一个元素。 - public E removeFirst():移除并返回此列表的第一个元素。 - public E removeLast():移除并返回此列表的最后一个元素。 - public E pop():从此列表所表示的堆栈处弹出一个元素。 - public void push(E e):将元素推入此列表所表示的堆栈。 小结: LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的。 所以提供了很多操作首尾元素的特殊API可的实以做栈和队列现。 如果查询多而增删少用ArrayList集合。(用的最多的) 如果查询少而增删首尾较多用LinkedList集合。 */ public class ListDemo03 { public static void main(String[] args) { // LinkedList可以完成队列结构,和栈结构 (双链表) // 1、做一个队列: LinkedList<String> queue = new LinkedList<>(); // 入队 来了排队排最后 queue.addLast("1号"); queue.addLast("2号"); queue.addLast("3号"); System.out.println(queue); // 出队 第一个先走 // System.out.println(queue.getFirst()); System.out.println(queue.removeFirst()); System.out.println(queue.removeFirst()); System.out.println(queue); // 2、做一个栈 LinkedList<String> stack = new LinkedList<>(); // 入栈 压栈 (push) 永远排第一个 stack.push("第1颗子弹"); stack.push("第2颗子弹"); stack.push("第3颗子弹"); stack.push("第4颗子弹"); System.out.println(stack); // 出栈 弹栈 pop 第一个先走 System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack); } }
7、集合的并发修改异常问题:同时遍历,同时删除
遍历删除集合元素的时候,不要用集合的remove方法,要用迭代器的remove方法
第五节 泛型深入
1、泛型概述和优势
2、自定义泛型类
3、自定义泛型方法

1 package com.itheima.d9_genericity_method; 2 3 /** 4 目标:自定义泛型方法。 5 6 什么是泛型方法? 7 定义了泛型的方法就是泛型方法。 8 9 泛型方法的定义格式: 10 修饰符 <泛型变量> 返回值类型 方法名称(形参列表){ 11 12 } 13 注意:方法定义了是什么泛型变量,后面就只能用什么泛型变量。 14 泛型类的核心思想:是把出现泛型变量的地方全部替换成传输的真实数据类型。 15 16 需求:给你任何一个类型的数组,都能返回它的内容。Arrays.toString(数组)的功能! 17 18 小结: 19 泛型方法可以让方法更灵活的接收数据,可以做通用技术! 20 */ 21 public class GenericDemo { 22 public static void main(String[] args) { 23 String[] names = {"小璐", "蓉容", "小何"}; 24 printArray(names); 25 26 Integer[] ages = {10, 20, 30}; 27 printArray(ages); 28 29 Integer[] ages2 = getArr(ages); 30 String[] names2 = getArr(names); 31 } 32 33 public static <T> T[] getArr(T[] arr){ 34 return arr; 35 } 36 37 public static <T> void printArray(T[] arr){ 38 if(arr != null){ 39 StringBuilder sb = new StringBuilder("["); 40 for (int i = 0; i < arr.length; i++) { 41 sb.append(arr[i]).append(i == arr.length - 1 ? "" : ", "); 42 } 43 sb.append("]"); 44 System.out.println(sb); 45 }else { 46 System.out.println(arr); 47 } 48 } 49 }
4、自定义泛型接口
5、泛型通配符、上下限
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App