day17.集合
课前回顾:
1.wait():线程等待,在等待的过程中,会释放锁,需要其他线程调用notify将其唤醒,醒来之后重新抢锁,抢到了,继续执行,抢不到锁阻塞
2.notify():一次唤醒一条等待的线程,如果有多条线程等待,随机唤醒一条
3.notifyAll():一次唤醒所有等待线程
4.格式:()->{}
a.():重写方法的参数位置
b.->:可以理解为将参数传递到方法体中
c.{}:重写方法的方法体
5.单例模式:一个类只产生一个对象
饿汉式
懒汉式
6.函数式接口:有且只有一个抽象方法的接口 -> @FunctionalInterface
Supplier Consumer Function Predicate
7.初学怎么写lambda:
a.先观察,看看是否是函数式接口做方法参数传递
b.如果是,调用方法时,以匿名内部类的方式传递实参
c.从new接口到重写方法的方法名结束,选中,删除,别忘记删除右半个大括号
d.在参数和方法体之间加 ->
8.省略规则:
a.参数类型可以省略
b.如果只有一个参数时,所在的小括号可以省略
c.方法体只有一句话,大括号,分号都可以干掉
d.方法体只有一句话,而且是带return的,大括号,分号以及return都可以干掉
今日重点:
a.会使用Stream流操作
b.记住单列集合的集合框架体系
c.会使用Collection接口中的方法
d.会使用迭代器遍历集合
e.知道ArrayList以及LinkedList的集合特点以及使用
第一章.Stream 流
1.Stream流:其中的"流"不是"IO流",可以理解为"流水线"的"流",下一个操作都是在上一个操作的基础上完成的

public class Demo01Stream {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("古力娜扎");
list.add("迪丽热巴");
list.add("马尔扎哈");
list.add("张三");
list.add("张无忌");
list.add("马帅");
list.add("张杰");
list.add("鹿晗");
list.add("蔡徐坤");
list.add("张三丰");
list.add("张友人");
// 1.过滤出姓张的元素
/* ArrayList<String> zhangList = new ArrayList<>();
for (String s : list) {
if (s.startsWith("张")) {
zhangList.add(s);
}
}*/
// 2.只要三个字的元素
/*ArrayList<String> threeList = new ArrayList<>();
for (String s : zhangList) {
if (s.length() == 3) {
threeList.add(s);
}
}*/
// 3.遍历
/*for (String s : threeList) {
System.out.println(s);
}*/
Stream<String> stream = list.stream();
stream.filter(s -> s.startsWith("张")).filter(s -> s.length()==3).forEach(s -> System.out.println(s));
}
}
1.Stream 的获取
1.针对集合:
default Stream<E> stream()
2.针对数组:Stream类中的静态方法
static <T> Stream<T> of(T... values)
public class Demo02Stream {
public static void main(String[] args) {
/*
1.针对集合:
default Stream<E> stream()
*/
ArrayList<String> list = new ArrayList<>();
list.add("古力娜扎");
list.add("迪丽热巴");
list.add("马尔扎哈");
list.add("雷霆嘎巴");
Stream<String> stream = list.stream();
System.out.println(stream);
/*
2.针对数组:Stream类中的静态方法
static <T> Stream<T> of(T... values)
*/
Stream<String> stream2 = Stream.of("李易峰", "吴亦凡", "郑爽", "吴秀波");
System.out.println("stream2 = " + stream2);
}
}
2.Stream 的方法
2.1.Stream 中的 forEach 方法:void forEach(Consumer<? super T> action);
forEach : 逐一处理->遍历
void forEach(Consumer<? super T> action);
注意:forEach方法是一个[终结方法],使用完之后,Stream流不能用了
public class Demo03Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("月亮之上", "荷塘月色", "秋天不回来", "两只蝴蝶", "认错");
/* stream.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
System.out.println("========================");
stream.forEach(s-> System.out.println(s));
}
}
2.2.Stream 中的 long count()
方法
1.作用:统计元素个数
2.注意:count也是一个终结方法
public class Demo04Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("月亮之上", "荷塘月色", "秋天不回来", "两只蝴蝶", "认错");
long count = stream.count();
System.out.println("count = " + count);
}
}
2.3.Stream 中的 Stream<T> filter(Predicate<? super T> predicate)
方法
1.方法:Stream<T> filter(Predicate<? super T> predicate)方法,返回一个新的Stream流对象
2.作用:根据某个条件进行元素过滤
public class Demo05Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("月亮之上", "荷塘月色", "秋天不回来", "两只蝴蝶", "认错");
/*Stream<String> stream1 = stream.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() > 2;
}
});
stream1.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
/* stream.filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() > 2;
}
}).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
System.out.println("==========================");
stream.filter(s -> s.length() > 2).forEach(s -> System.out.println(s));
}
}
2.4.Stream<T> limit(long maxSize)
:获取 Stream 流对象中的前 n 个元素,返回一个新的 Stream 流对象
1.Stream<T> limit(long maxSize):获取Stream流对象中的前n个元素,返回一个新的Stream流对象
public class Demo06Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("月亮之上", "荷塘月色", "秋天不回来", "两只蝴蝶", "认错");
stream.limit(3).forEach(s -> System.out.println(s));
}
}
2.5.Stream<T> skip(long n)
: 跳过 Stream 流对象中的前 n 个元素,返回一个新的 Stream 流对象
Stream<T> skip(long n): 跳过Stream流对象中的前n个元素,返回一个新的Stream流对象
public class Demo07Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("月亮之上", "荷塘月色", "秋天不回来", "两只蝴蝶", "认错");
stream.skip(3).forEach(s -> System.out.println(s));
}
}
2.6.static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
:两个流合成一个流
1.方法:static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b):两个流合成一个流
public class Demo08Stream {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("月亮之上", "荷塘月色", "秋天不回来", "两只蝴蝶", "认错");
Stream<String> stream2 = Stream.of("灰色头像", "庐州月", "清明雨上", "幻听", "星座书上");
Stream.concat(stream1, stream2).forEach(s -> System.out.println(s));
}
}
2.7.将 Stream 流变成集合
从Stream流对象转成集合对象,使用Stream接口方法collect()
public class Demo09Stream {
public static void main(String[] args) {
Stream<String> stream1 = Stream.of("月亮之上", "荷塘月色", "秋天不回来", "两只蝴蝶", "认错");
List<String> list = stream1.collect(Collectors.toList());
System.out.println(list);
}
}
2.8.dinstinct 方法
Stream<T> distinct()
元素去重复,重写hashCode和equals方法
public class Person {
private String name;
private Integer age;
public Person() {
}
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return Objects.equals(name, person.name) && Objects.equals(age, person.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
public class Demo10Stream {
public static void main(String[] args) {
Stream<String> stream = Stream.of("张无忌", "赵敏", "周芷若", "小昭", "宋青书", "张三丰", "张无忌");
stream.distinct().forEach(s -> System.out.println(s));
Stream<Person> stream2 = Stream.of(new Person("张三", 10), new Person("李四", 15), new Person("张三", 10));
stream2.distinct().forEach(p -> System.out.println(p));
}
}
2.9.转换流中的类型
Stream<R> map(Function<T,R> mapper)-> 转换流中的数据类型
public class Demo11Stream {
public static void main(String[] args) {
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
/* stream.map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return integer + "";
}
}).forEach(s -> System.out.println(s+1));*/
stream.map(s -> s + "").forEach(s -> System.out.println(s + 1));
}
}
2.10.Stream 流练习
1. 第一个队伍只要名字为3个字的成员姓名;//filter
2. 第一个队伍筛选之后只要前3个人;//limit
3. 第二个队伍只要姓张的成员姓名;//filter
4. 第二个队伍筛选之后不要前2个人;//skip
5. 将两个队伍合并为一个队伍;//concat
6. 打印整个队伍的姓名信息;//forEach
public class Demo12Stream {
public static void main(String[] args) {
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("老子");
one.add("庄子");
one.add("孙子");
one.add("洪七公");
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("张三丰");
two.add("赵丽颖");
two.add("张二狗");
two.add("张天爱");
two.add("张三");
Stream<String> streamA = one.stream();
Stream<String> streamB = two.stream();
//Stream<String> stream1 = streamA.filter(s -> s.length() == 3).limit(3);
//Stream<String> stream2 = streamB.filter(s -> s.startsWith("张")).skip(2);
Stream.concat(streamA.filter(s -> s.length() == 3).limit(3), streamB.filter(s -> s.startsWith("张")).skip(2)).forEach(s -> System.out.println(s));
}
}
第二章.方法引用&其他新特性
1.方法引用的介绍
1.概述:就是在Lambda表达式的基础上再次简化
2.条件:
a.被引用的方法需要在重写的方法中被引用
b.被引用的方法从参数上以及返回值上要和所在的重写的方法一样
c.干掉重写方法的参数位置以及->,以及被引用方法的参数,将调用方法的.改成::
2.方法引入的体验
public class Demo01Method {
public static void main(String[] args) {
Stream<String> stream = Stream.of("张三丰", "张翠山", "张无忌", "赵敏", "殷素素", "殷天正", "殷野王");
/* stream.forEach(new Consumer<String>() {
*//*
accept是重写的方法,参数是一个String的,没有返回值
println有一个String的参数,没有返回值
*//*
@Override
public void accept(String s) {
System.out.println(s);
}
});*/
System.out.println("==========================");
stream.forEach(System.out::println);
}
}
3.对象名--引用成员方法
1.使用对象名引用成员方法
格式:
对象::成员方法名
2.需求:
函数式接口:Supplier
java.util.function.Supplier<T>接口
抽象方法:
T get()。用来获取一个泛型参数指定类型的对象数据。
Supplier接口使用什么泛型,就可以使用get方法获取一个什么类型的数据
public class Demo02Method {
public static void main(String[] args) {
method(new Supplier<String>() {
/*
get方法是重写的方法,无参,返回值类型String
trim方法无参,返回值类型String
*/
@Override
public String get() {
return " abc ".trim();
}
});
System.out.println("--------------------------");
method(()-> " abc ".trim());
System.out.println("===========================");
method(" abc "::trim);
}
public static void method(Supplier<String> supplier){
String s = supplier.get();
System.out.println("s = " + s);
}
}
4.类名--引用静态方法
类名--引用静态方法
格式:
类名::静态成员方法
public class Demo03Method {
public static void main(String[] args) {
method(new Supplier<Double>() {
/*
get方法是重写的方法,无参,返回值类型double
random方法无参,返回值类型double
*/
@Override
public Double get() {
return Math.random();
}
});
System.out.println("--------------------------");
method(()-> Math.random());
System.out.println("===========================");
method(Math::random);
}
public static void method(Supplier<Double> supplier){
Double v = supplier.get();
System.out.println("v = " + v);
}
}
5.类--构造引用
1. 类--构造方法引用
格式:
构造方法名称::new
2.需求:
函数式接口:Function
java.util.function.Function<T,R>接口
抽象方法:
R apply(T t),根据类型T的参数获取类型R的结果。用于数类型转换
public class Demo04Method {
public static void main(String[] args) {
method(new Function<String, Person>() {
/*
apply方法是重写方法,参数类型String,返回值类型Person
Person(String name)参数类型String,返回值类型Person
*/
@Override
public Person apply(String s) {
return new Person(s);
}
},"张三");
System.out.println("--------------------------");
method(s-> new Person(s),"张三");
System.out.println("===========================");
method(Person::new,"李四");
}
public static void method(Function<String,Person> function,String name){
Person person = function.apply(name);
System.out.println(person);
}
}
6.数组--数组引用
数组--数组引用
格式:
数组的数据类型[]::new
int[]::new 创建一个int型的数组
double[]::new 创建于一个double型的数组
public class Demo05Method {
public static void main(String[] args) {
method(new Function<Integer, int[]>() {
/*
apply方法重写,参数类型Integer,返回值类型int[]
int[] arr = new int[integer]
参数为Integer,返回值类型int[]
*/
@Override
public int[] apply(Integer integer) {
return new int[integer];
}
},100);
System.out.println("===========================");
method(len->new int[len],100);
System.out.println("===========================");
method(int[]::new,100);
}
public static void method(Function<Integer,int[]> function, Integer len){
int[] arr = function.apply(len);
System.out.println(arr.length);
}
}
github -> 搜索毕设
7.Record 类
Record 类在 JDK14、15 预览特性,在 JDK16 中转正。
record 是一种全新的类型,它本质上是一个 final 类,同时所有的属性都是 final 修饰,它会自动编译出 get、hashCode 、比较所有属性值的 equals、toString 等方法,减少了代码编写量。使用 Record 可以更方便的创建一个常量类。
1.注意:
Record 只会有一个全参构造
重写的 equals 方法比较所有属性值
可以在 Record 声明的类中定义静态字段、静态方法或实例方法(非静态成员方法)。
不能在 Record 声明的类中定义实例字段(非静态成员变量);
类不能声明为 abstract;
不能显式的声明父类,默认父类是 java.lang.Record 类
因为 Record 类是一个 final 类,所以也没有子类等。
javapublic record Person(String name) { //int i;//不能声明实例变量 static int i;//可以声明静态变量 //不能声明空参构造 /* public Person(){ }*/ //可以声明静态方法 public static void method(){ } //可以声明非静态方法 public void method01(){ } }
javapublic class Test01 { public static void main(String[] args) { Person person = new Person("张三"); Person person1 = new Person("张三"); System.out.println(person); System.out.println(person.equals(person1)); } }
8.密封类
其实很多语言中都有密封类
的概念,在 Java 语言中,也早就有密封类
的思想,就是 final 修饰的类,该类不允许被继承。而从 JDK15 开始,针对密封类
进行了升级。
Java 15 通过密封的类和接口来增强 Java 编程语言,这是新引入的预览功能并在 Java 16 中进行了二次预览,并在 Java17 最终确定下来。这个预览功能用于限制超类的使用,密封的类和接口限制其他可能继承或实现它们的其他类或接口。
【修饰符】 sealed class 密封类 【extends 父类】【implements 父接口】 permits 子类{
}
【修饰符】 sealed interface 接口 【extends 父接口们】 permits 实现类{
}
- 密封类用 sealed 修饰符来描述,
- 使用 permits 关键字来指定可以继承或实现该类的类型有哪些
- 一个类继承密封类或实现密封接口,该类必须是 sealed、non-sealed、final 修饰的。
- sealed 修饰的类或接口必须有子类或实现类
public sealed class Animal permits Dog,Cat{
}
public non-sealed class Dog extends Animal{
}
public non-sealed class Cat extends Animal{
}
package com.atguigu.sealed;
import java.io.Serializable;
public class TestSealedInterface {
}
sealed interface Flyable /*extends Serializable*/ permits Bird {
}
non-sealed class Bird implements Flyable{
}
第三章.集合框架(单列集合)
1.概述:容器
2.作用:一次存储多个数据
3.特点:
a.长度可变
b.只能存储引用类型的数据(如果存基本类型,到了集合中会自动转成包装类型)
4.分类:
a.单列集合:一个元素只由一部分构成
list.add("张三")
b.双列集合:一个元素由两部分构成(key和value),称之为键值对
map.put("涛哥","金莲")

第四章.Collection 接口
1.概述:Collection是单列集合的顶级接口
2.使用:
Collection<元素的数据类型> 集合名 = new 实现类对象<>()
3.泛型:
a.作用:同一元素的数据类型
b.<>里面只能写引用类型,不能写基本类型,如果想操作基本类型数据,那么就写包装类
c.如果不指定泛型类型,元素默认类型就是Object
4.常用方法:
boolean add(E e) : 将给定的元素添加到当前集合中(我们一般调add时,不用boolean接收,因为add一定会成功)
boolean addAll(Collection<? extends E> c) :将另一个集合元素添加到当前集合中 (集合合并)
void clear():清除集合中所有的元素
boolean contains(Object o) :判断当前集合中是否包含指定的元素
boolean isEmpty() : 判断当前集合中是否有元素->判断集合是否为空
boolean remove(Object o):将指定的元素从集合中删除
int size() :返回集合中的元素个数。
Object[] toArray(): 把集合中的元素,存储到数组中
public class Demo01Collection {
public static void main(String[] args) {
Collection<String> collection = new ArrayList<>();
//boolean add(E e) : 将给定的元素添加到当前集合中(我们一般调add时,不用boolean接收,因为add一定会成功)
collection.add("张作霖");
collection.add("熊二");
collection.add("张学良");
System.out.println(collection);
//boolean addAll(Collection<? extends E> c) :将另一个集合元素添加到当前集合中 (集合合并)
Collection<String> collection1 = new ArrayList<>();
collection1.add("哪吒");
collection1.add("木吒");
collection1.add("金吒");
collection.addAll(collection1);
System.out.println(collection);
//void clear():清除集合中所有的元素
collection.clear();
System.out.println(collection);
//boolean contains(Object o) :判断当前集合中是否包含指定的元素
System.out.println(collection.contains("哪吒"));
//boolean isEmpty() : 判断当前集合中是否有元素->判断集合是否为空
System.out.println(collection.isEmpty());
//boolean remove(Object o):将指定的元素从集合中删除
collection1.remove("哪吒");
System.out.println(collection1);
//int size() :返回集合中的元素个数。
System.out.println(collection1.size());
//Object[] toArray(): 把集合中的元素,存储到数组中
Object[] arr = collection1.toArray();
System.out.println(Arrays.toString(arr));
}
}
第五章.迭代器
1.迭代器基本使用
1.概述:Iterator接口
2.作用:遍历集合的
3.获取:Collection中的方法
Iterator<E> iterator()
4.Iterator中的方法:
boolean hasNext()判断有没有下一个元素
E next() 获取下一个元素
public class Demo02Iterator {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("大耳朵图图");
list.add("百变小樱");
list.add("巴啦啦小魔仙");
list.add("甜心格格");
list.add("小马宝莉");
list.add("爱神巧克力");
list.add("猫眼三姐妹");
//获取迭代器对象
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String name = iterator.next();
System.out.println(name);
}
}
}
javapublic class Demo01Iterator { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("大耳朵图图"); list.add("百变小樱"); list.add("巴啦啦小魔仙"); list.add("甜心格格"); list.add("小马宝莉"); list.add("爱神巧克力"); //list.add("猫眼三姐妹"); //获取迭代器对象 Iterator<String> iterator = list.iterator(); while(iterator.hasNext()){ String name = iterator.next(); String name1 = iterator.next(); System.out.println(name); System.out.println(name1); } } }
Exception in thread "main" java.util.NoSuchElementException at java.base/java.util.ArrayList$Itr.next(ArrayList.java:970) at com.atguigu.c_collection.Demo02Iterator.main(Demo02Iterator.java:21)
2.迭代器迭代过程

3.迭代器底层原理
1.Iterator<String> iterator = list.iterator();等号左边是接口类型,那么等号右边一定是Iterator接口的实现类对象,所以问,Iterator接口此时接收了哪个实现类对象?
2.接收的是ArrayList的内部类Itr

javapublic class Demo02Iterator { public static void main(String[] args) { HashSet<String> set = new HashSet<>(); set.add("张三"); set.add("李四"); set.add("王五"); Iterator<String> iterator = set.iterator(); while(iterator.hasNext()){ String name = iterator.next(); System.out.println(name); } } }
4.并发修改异常
需求:定义一个集合,存储 唐僧,孙悟空,猪八戒,沙僧,遍历集合,如果遍历到猪八戒,往集合中添加一个白龙马
错误代码
public class Demo03Iterator {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("唐三藏");
list.add("孙悟空");
list.add("猪八戒");
list.add("沙和尚");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String name = iterator.next();
if ("猪八戒".equals(name)){
list.add("白龙马");
}
}
System.out.println(list);
}
}
总结一句话:使用迭代器遍历集合的过程中不要随意修改集合长度-> 尤其是添加操作
1.出现并发修改异常的原因:
当实际操作次数和预期操作次数不相等时,会出现并发修改异常
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
2.我们干啥了,让实际操作次数和预期操作次数不相等了
list.add("白龙马")
=================================================
public boolean add(E e) {
modCount++;
add(e, elementData, size);
return true;
}
添加完之后,modCount++了,然后紧接着调用了next方法
public E next() {
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
结论:我们调用add方法之后,底层单独给实际操作次数加1了,然后紧接着调用next方法,next方法底层做了判断,此时发现实际操作次数和预期操作次数不相等了,所以抛出了并发修改异常
扩展:ListIterator
public class Demo04Iterator {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("唐三藏");
list.add("孙悟空");
list.add("猪八戒");
list.add("沙和尚");
ListIterator<String> listIterator = list.listIterator();
while (listIterator.hasNext()) {
String name = listIterator.next();
if ("猪八戒".equals(name)){
listIterator.add("白龙马");
}
}
System.out.println(list);
}
}
第六章.数据结构
数据结构是一种具有一定逻辑关系,在计算机中应用某种存储结构,并且封装了相应操作的数据元素集合。它包含三方面的内容,逻辑关系、存储关系及操作。
为什么需要数据结构
随着应用程序变得越来越复杂和数据越来越丰富,几百万、几十亿甚至几百亿的数据就会出现,而对这么大对数据进行搜索、插入或者排序等的操作就越来越慢,数据结构就是用来解决这些问题的。
数据的逻辑结构指反映数据元素之间的逻辑关系,而与他们在计算机中的存储位置无关:
- 集合(数学中集合的概念):数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系;
- 线性结构:数据结构中的元素存在一对一的相互关系;
- 树形结构:数据结构中的元素存在一对多的相互关系;
- 图形结构:数据结构中的元素存在多对多的相互关系。
数据的物理结构/存储结构:是描述数据具体在内存中的存储(如:顺序结构、链式结构、索引结构、哈希结构)等,一种数据逻辑结构可表示成一种或多种物理存储结构。
数据结构是一门完整并且复杂的课程,那么我们今天只是简单的讨论常见的几种数据结构,让我们对数据结构与算法有一个初步的了解。
1.栈
1.特点:
先进后出

2.队列
1.特点:先进先出
3.数组
1.特点:查询快,增删慢
a.查询快:有索引,可以根据所有快速定位到指定的元素位置
b.添加一个元素->创建新数组,将老数组元素放到新数组中去,将新数组地址值复制给老数组
删除元素->如果删除中间元素,元素还得往前移动
4.链表
1.特点:
查询慢,增删快
2.单向链表
3.双向链表
4.1 单向链表
1.特点:前面节点记录后面节点地址,但是后面节点不会记录前面节点地址
2.一个节点分成两部分
第一部分:数据域-> 存储数据
第二部分:指针域-> 存储下一个节点地址
3.底层数据结构是单向链表的 -> 不能保证元素有序

4.2 双向链表
1.特点:前面节点记录后面节点地址,后面节点记录前面节点地址
2.一个节点分成三部分
第一部分:指针域 -> 记录上一级节点的地址
第二部分:数据域 -> 存储的数据
第三部分:指针域 -> 记录下一个节点的地址
3.底层数据结构是双向链表的 -> 能保证元素有序

第七章.List 接口
1.概述:Collection接口的子接口
2.实现类:
ArrayList LinkedList Vector
第八章.List 集合下的实现类
1.ArrayList 集合
1.概述:是List接口的实现类
2.特点:
a.元素有序
b.有索引
c.元素可重复
d.线程不安全
3.数据结构:
数组
1.1.ArrayList 集合使用
1.常用方法:
boolean add(E e) -> 将元素添加到集合中->尾部(add方法一定能添加成功的,所以我们不用boolean接收返回值)
void add(int index, E element) ->在指定索引位置上添加元素
boolean remove(Object o) ->删除指定的元素,删除成功为true,失败为false
E remove(int index) -> 删除指定索引位置上的元素,返回的是被删除的那个元素
E set(int index, E element) -> 将指定索引位置上的元素,修改成后面的element元素
E get(int index) -> 根据索引获取元素
int size() -> 获取集合元素个数
public class Demo01List {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
//boolean add(E e) -> 将元素添加到集合中->尾部(add方法一定能添加成功的,所以我们不用boolean接收返回值)
list.add("张三");
list.add("李四");
list.add("王五");
list.add("赵六");
System.out.println(list);
//void add(int index, E element) ->在指定索引位置上添加元素
list.add(0, "田七");
System.out.println(list);
//boolean remove(Object o) ->删除指定的元素,删除成功为true,失败为false
list.remove("赵六");
System.out.println(list);
//E remove(int index) -> 删除指定索引位置上的元素,返回的是被删除的那个元素
System.out.println(list.remove(0));
System.out.println(list);
//E set(int index, E element) -> 将指定索引位置上的元素,修改成后面的element元素
list.set(0,"涛哥");
System.out.println("list = " + list);
//E get(int index) -> 根据索引获取元素
System.out.println(list.get(0));
//int size() -> 获取集合元素个数
System.out.println(list.size());
System.out.println("==============================");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("===============================");
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
小谷易考通->微信