集合的体系结构
![图片[1]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/yuque_diagram-1.png)
Collection概述和使用
- 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
- JDK不提供此接口的任何直接实现,它可以使用其子接口(List和Set)的具体类实现
- 使用多态的方式创建其对象
Collection单列集合常用方法
![图片[2]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-43.png)
代码演示 :
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
public class CollectionMethodDemo {
/*
Collection单列集合常用方法 :
*/
public static void main(String[] args) {
Collection<String> c = new ArrayList<>();
c.add("张三");
c.add("李四");
c.add("王五");
boolean b = c.remove("李四");
System.out.println(b);
System.out.println("--------------------");
System.out.println(c.contains("李四"));
System.out.println(c.contains("张三"));
System.out.println("--------------------");
System.out.println(c.isEmpty());
c.clear();
System.out.println(c.isEmpty());
System.out.println("--------------------");
System.out.println(c.size());
}
private static void method() {
// 对象的创建: 使用多态的形式创建
// 目的: 多态调用方法, 只能调用共有方法
Collection<String> c = new ArrayList<>();
c.add("张三");
c.add("张三");
c.add("张三");
System.out.println("清空前: " + c);
c.clear();
System.out.println("清空后: " + c);
}
}
集合的通用遍历格式
迭代器(代码演示)
/*
集合的通用遍历方式 : 迭代器(Iterator)遍历
1. 通过集合对象, 获取迭代器
2. 循环判断, 集合中是否存在元素
3. 调用方法取出元素
*/
private static void method1(Collection<Student> c) {
// 1. 通过集合对象, 获取迭代器
Iterator<Student> it = c.iterator();
// Iterator<Student> it = new Itr();
// 2. 循环判断, 集合中是否存在元素
while (it.hasNext()) {
// 3. 调用方法取出元素
Student stu = it.next(); // next() : 先将元素取出来, 再将内部的指针向后移动一位
System.out.println(stu);
}
}
增强for(代码演示)
/*
增强for循环 : 迭代器的语法糖
- 底层实现也是迭代器
- 格式 :
for(容器中存储的元素类型 变量名 : 要遍历的容器名字){
// 变量名 : 就是从容器中取出的元素
}
*/
private static void method2(Collection<Student> c) {
for (Student stu : c) {
System.out.println(stu);
}
}
foreach(代码演示)
/*
调用集合的foreach方法进行遍历
public default void forEach(Consumer<? super T> action) :
Consumer : 函数式接口
形参是接口, 实际参数该给实现类对象
1. 单独编写一个实现类
2. 匿名内部类
3. Lambda
*/
public static void main(String[] args) {
Collection<Student> c = new ArrayList<>();
c.add(new Student("张三", 23));
c.add(new Student("李四", 24));
c.add(new Student("王五", 25));
// forEach方法配合 匿名内部类, 其实底层也是迭代器
c.forEach(new Consumer<Student>() {
@Override
public void accept(Student stu) {
System.out.println(stu);
}
});
System.out.println("------------------------");
c.forEach(s -> System.out.println(s));
}
三个迭代器练习完整代码 :
import com.itheima.domain.Student;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
public class IteratorDemo {
public static void main(String[] args) {
Collection<Student> c = new ArrayList<>();
c.add(new Student("张三", 23));
c.add(new Student("李四", 24));
c.add(new Student("王五", 25));
c.forEach(new Consumer<Student>() {
@Override
public void accept(Student stu) {
System.out.println(stu);
}
});
System.out.println("------------------------");
c.forEach(s -> System.out.println(s));
}
private static void method2(Collection<Student> c) {
for (Student stu : c) {
System.out.println(stu);
}
}
private static void method1(Collection<Student> c) {
// 1. 通过集合对象, 获取迭代器
Iterator<Student> it = c.iterator();
// Iterator<Student> it = new Itr();
// 2. 循环判断, 集合中是否存在元素
while (it.hasNext()) {
// 3. 调用方法取出元素
Student stu = it.next(); // next() : 先将元素取出来, 再将内部的指针向后移动一位
System.out.println(stu);
}
}
}
List接口
![图片[3]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-44.png)
![图片[4]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-45.png)
代码演示 :
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
/*
List接口:
特点: 存取有序, 有索引, 可以存储重复的
- 因为有索引, 提供很多用索引操作元素的方法.
注意: List接口中的集合, 因为有索引, 所以多了一种遍历方式
- 迭代器
- 增强for
- foreach
- 普通for
- List特有接口, ListIterator
*/
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
}
}
并发修改异常
- ConcurrentModificationException
ConcurrentModificationException 并发修改异常:
原因 : 当使用[迭代器]在遍历集合的时候, 调用了[集合对象]的添加, 或者是删除的方法, 就会出现并发修改异常
解决方案 :
就使用迭代器自己的添加或者删除方法
细节:
别除方法:Iterator里面有
添加方法:ListIterator迭代器里面有
问题: 那如果真的有业务场景, 需要在迭代器遍历的过程中, 删除集合元素, 怎么解决?
回答: 使用迭代器自己的删除方法
迭代器在遍历
迭代在在删除
问题: 需要在迭代器遍历的过程中, 添加怎么解决?
- Iterator内部不存在添加的方法
回答: 换一个迭代器 ListIterator (List集合特有的迭代器)
--------------------------------------------------------------------------------------------------------
恶心的问题 : 迭代器在遍历的时候做删除, 如果删除的是集合的倒数第二个元素, 就没有并发修改异常
- 原因: 略过了check方法的检测
使用List接口特有的迭代器ListIterator
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
ListIterator<String> it = list.listIterator();
while (it.hasNext()) {
String s = it.next();
if ("李四".equals(s)) {
it.add("周七");
}
}
System.out.println(list);
}
迭代器在遍历的时候做删除, 如果删除的是集合的倒数第二个元素, 就没有并发修改异常
– 原因: 略过了check方法的检测
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("bbb");
list.add("def");
list.add("ccc");
list.add("ddd");
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
if ("def".equals(s)) {
it.remove();
}
}
System.out.println(list);
}
Set接口
- 特点
其元素不可重复,使用方法基本与Collection集合一致
- 实现类
HashSet:由哈希表支持,对集合的迭代顺序不保证,同时没有带索引的方法,不能使用普通for循环遍历
- 哈希值
是JDK根据对象的地址形成的int类型的值,可通过对象的HashCode方法得到。对象类中未重写HashCode与equals方法时,不同对象哈希值不相同。若在对象中重写HashCode方法可以自定哈希值
- 哈希表
底层采用数组+链表实现,可以说元素是链表的数组,长度为16
存储原理:通过获得对象的哈希值对16取余,得到存储的位置,然后比较依次比较哈希值和元素内容,都不同时存入元素
- 注意事项
⭐若要使HashSet集合不能储存相同内容,则必须重写对象的HashCode与equals方法!!!
Map集合概述和使用
Map集合的特点
Interface Map<K,V> K:键的类型 V:值的类型
将键映射到值的对象,不包含重复的键,每个键最多只能映射一个值
当键重复时,后录入的值会替换前面的值,原理是通过Hash表实现
Map双列集合常用方法
方法名 | 说明 |
Object put(Object key, Object value) | 以“键-值”对的方式进行存储 |
Object get(Object key) | 根据键返回相关联的值,如果不存在指定的键,返回null |
Object remove(Object key) | 删除由指定的键映射的“键-值对” |
int size( ) | 返回元素个数 |
Set keySet( ) | 返回键的集合 |
Collection values( ) | 返回值的集合 |
boolean containsKey(Object key) | 如果存在由指定的键映射的“键-值对”,返回true |
Map集合的两种遍历方式
使用键集合
Set<String> keys = map.keySet();
for (String key:keys){
String vaule = map.get(key);
System.out.println(key+","+vaule);
}
使用键值对对象
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> s:entries){
String key = s.getKey();
String value = s.getValue();
System.out.println(key+","+value);
}
注意点
⭐在HashMap集合中,若键的类型为自定义类型时,若要保证键的唯一性,必须在其类中重写HashCode与equals方法
数据结构
数据结构介绍
![图片[5]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-46.png)
数据结构(栈, 队列)
![图片[6]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-47.png)
数据结构(数组)
![图片[7]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-48.png)
数据结构(链表)
单链表介绍和演示
![图片[8]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-49.png)
![图片[9]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-50.png)
![图片[10]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-51.png)
双链表的介绍和演示
![图片[11]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-52.png)
![图片[12]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-53.png)
![图片[13]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-54.png)
ArrayList类、LinkedList类
ArrayList类
ArrayList类底层是基于数组实现的,根据查询元素快,增删相对慢
ArrayList长度可变原理
- 如果只是创建了集合容器,没有进行过添加操作,底层数组默认长度为0
- ArrayList底层是数组结构的,数组默认长度为10
- 当数组添加满了之后,会自动扩容为1.5倍
LinkedList类
LinkedList 底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的
![图片[14]-4.0 集合-数据结构-ArrayList、LinkedList类-IT熊技术站](https://www.cutrui.cn/wp-content/uploads/2023/08/image-55-edited.png)
思考
LinkedList也有get方法,表面看起来是根据索引获取元素,实际上是?
回答 : 会将get方法收到的索引做if判断 , 看里头部近 , 还是尾部近 , 离谁近 , 就从哪个部分开始获取
暂无评论内容