1. 异常

1.1 异常的概述

Error:严重问题,不需要处理
Exception:称为异常类,它表示程序本身可以处理的问题

  • RuntimeException:在编译期是不检查的,出现问题后,需要我们回来修改代码
  • 非RuntimeException:编译期就必须处理的,否则程序不能粉通过编译,就更不能正常运行了

1.2 JVM的默认处理方案

如果程序出现了问题,我们没有做任何处理,最终JVM会做默认的处理

  • 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
  • 程序停止执行

1.3 异常处理try…catch…

  • 格式:
1
2
3
4
5
try{
//可能出现异常的代码
}catch(异常类名 变量名){
//异常的处理代码
}
  • 执行流程
  1. 程序从try里面的代码开始执行

  2. 出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统

  3. 当Java运行时系统接收到异常对象时,会到catch中去找匹的异常类,找到后进行异常的处理

  4. 执行完毕之后,程序还可以继续往下执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package demo_01;

/*try{
可能出现异常的代码
}catch(异常类名 变量名){
异常的处理代码
}*/
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}

public static void method() {
int[] arr = {15, 22, 66, 88};
try {
System.out.println(arr[4]); //ArrayIndexOutOfBoundsException
}catch(ArrayIndexOutOfBoundsException e){ //new ArrayIndexOutOfBoundsException
System.out.println("访问的索引越界");
e.printStackTrace();
}
}
}

1.4 Throwable的成员方法

方法名 说明
public String getMessage() 返回此throwable的详细消息字符串
public String toString() 返回此可抛出的简短描述
public void printStackTrace() 把异常的错误信息输出在控制台
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package demo_01;

/*try{
可能出现异常的代码
}catch(异常类名 变量名){
异常的处理代码
}*/
public class ExceptionDemo {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}

public static void method() {
int[] arr = {15, 22, 66, 88};
try {
System.out.println(arr[4]); //ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException
//public String toString()返回此可抛出的简短描述
System.out.println(e.toString());
System.out.println("------------");

//public String getMessage()返回此throwable的详细消息字符串
System.out.println(e.getMessage());
System.out.println("------------");

//public void printStackTrace()把异常的错误信息输出在控制台
e.printStackTrace();
}
}
}
//运行结果
开始
java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
------------
Index 4 out of bounds for length 4
------------
结束
java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
at demo_01.ExceptionDemo.method(ExceptionDemo.java:18)
at demo_01.ExceptionDemo.main(ExceptionDemo.java:11)

1.5 编译时异常和运行时异常的区别

Java中的异常被分为两大类:编译时异常运行时异常,也被称为受检异常非受检异常
所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常

  • 编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译
  • 运行时异常:无需显示处理,也可以和编译时异常一样处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package demo_01;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExceptionDemo_02 {
public static void main(String[] args) {
method();
method2();
}

//编译时异常
public static void method() {
try {
String s = "2022-04-24";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
} catch (ParseException e) {
e.printStackTrace();
}
}

//运行异常
public static void method2() {
try {
int[] arr = {55, 88, 99};
System.out.println(arr[3]); //ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("访问索引越界");
}
}
}

1.6 异常处理之throws

虽然我们通过ty…catch…可以对异常进行处理,但是并不是所有的情况我们都有权限进行异常的处理
也就是说,有些时候可能出现的异常是我们处理不了的,这个时候该怎么办呢?
针对这种情况,Java提供了throws的处理方案

  • 格式:
1
throws  异常类名;

注意:这个格式是跟在方法的括号后面的

  • 编译时异常必须要进行处理,两种处理方案:try…catch…或者throws,如果采用throws这种方案,将来谁调用谁处理
  • 运行时异常可以不处理,出现问题后,需要我们回来修改代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package demo_01;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*
throws 异常类名;
这个格式跟在方法名的后面
*/
public class ThrowsDemo {
public static void main(String[] args) {
System.out.println("开始");
try {
method();
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("结束");

}
//抛出异常等待调用者去处理 throws ParseException
//编译时异常
public static void method() throws ParseException {
String s = "2022-04-24";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse(s);
System.out.println(d);
}
}

1.7 自定义异常

  • 格式
1
2
3
4
5
6
7
8
9
10
11
12
//格式
public class 异常类名 extends Exception{
//无参构造
//带参构造
}
//范例
public class ScoreException extends Exception{
public ScoreException(){}
public ScoreException(String message){
super(message);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//1.
package scoreDemo;

public class ScoreException extends Exception{
public ScoreException() {
}

public ScoreException(String message) {
super(message);
}
}

//2.
package scoreDemo;

public class Teacher {
public void checkScore(int score) throws ScoreException{
if (score<0||score>100){
throw new ScoreException("分数输入的不正确");
}else {
System.out.println("分数正确");
}
}
}

//3.
package scoreDemo;

import java.util.Scanner;

public class TeacherDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("请输入分数:");
int score = sc.nextInt();

Teacher t= new Teacher();
try {
t.checkScore(score);
} catch (ScoreException e) {
e.printStackTrace();
}
}
}
//运行结果
请输入分数:98
分数正确

请输入分数:150
scoreDemo.ScoreException: 分数输入的不正确
at scoreDemo.Teacher.checkScore(Teacher.java:6)
at scoreDemo.TeacherDemo.main(TeacherDemo.java:13)

1.8 throws和throw的区别

throws throw
用在方法声明后面,跟的是异常类名 用在方法体内,跟的是异常对象名
表示抛出异常,由该方法的调用者来处理 表示抛出异常,由方法体内的语句处理
表示出现异常的一种可能性,并不一定会发生这些异常 执行throw一定抛出了某种异常

2.Collection

集合的特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变

2.1 集合体系结构

集合体系结构

2.2 Collection集合概述和使用

Collection集合概述

  • 是单列集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
  • JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现

创建Collection集合的对象

  • 多态的方式
  • 具体的实现类ArrayList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package collectionDemo_01;

import java.util.ArrayList;
import java.util.Collection;

/*
创建Collection集合对象
多态的方式
*/

public class CollectionDemo {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();

c.add("张三");
c.add("李四");
c.add("王五");
System.out.println(c);
}
}
//运行结果
[张三, 李四, 王五]

2.3 Collection集合常用方法

方法名 说明
boolean add(E e) 添加元素
boolean remove(Object o) 从集合中移除指定的元素
void clear() 清空集合中的元素
boolean contains(Object o) 判断集合中是否存在指定的元素
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中元素的个数

2.4 Collection集合的遍历

Iterator:迭代器,集合的专用遍历方式

  • Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
  • 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的

Iterator中的常用方法:

  • E next():返回迭代中的下一个元素
  • boolean hasNext():如果迭代具有更多元素,则返回true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package collectionDemo_01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

/*
创建Collection集合对象
多态的方式
*/

public class CollectionDemo {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();

c.add("张三");
c.add("李四");
c.add("王五");

Iterator<String> it = c.iterator();
//用while循环改进判断
while(it.hasNext()){
String n = it.next();
System.out.println(n);
}
}
}
//运行结果
张三
李四
王五

2.5 集合的使用步骤

步骤1

2.6 Collection集合存储学生对象并遍历

需求:创建一个存储学生对象的集合,存储3个学生对像,使用程序实现在控制台遍历该集合

思路:
①定义学生类
②创建Collection集合对像
③创建学生对象
④把学生添加到集合
⑤遍历集合(迭代器方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//1.定义学生类
package demo_02;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

//2.测试类
package demo_02;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo {
public static void main(String[] args) {
//创建Colection集合对象
Collection<Student> c = new ArrayList<Student>();

//创建学生对象
Student sc1 = new Student("张三", 18);
Student sc2 = new Student("李四", 19);
Student sc3 = new Student("王五", 10);

//把学生添加到集合
c.add(sc1);
c.add(sc2);
c.add(sc3);

//遍历集合(迭代器方式)
Iterator<Student> it = c.iterator();
while(it.hasNext()){
Student n = it.next();
System.out.println(n.getName()+", "+n.getAge());
}
}
}
//运行结果
张三, 18
李四, 19
王五, 10

3. List

3.1 List集合概述和特点

List集合概述:

  • 有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
  • 与Set集合不同,列表通常允许重复的元素

List集合特点:

  • 有序:存储和取出的元素顺序一致
  • 可重复:存储的元素可以重复
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package listDemo_03;

/*List集合特点:
有序:存储和取出的元素顺序一致
可重复:存储的元素可以重复*/

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListDemo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<>();

//添加元素
list.add("张三");
list.add("李四");
list.add("王五");
list.add("王五");

//输出集合对象
System.out.println(list);

//迭代器遍历集合
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String s = it.next();
System.out.println(s);
}
}
}
//运行结果
[张三, 李四, 王五, 王五]
张三
李四
王五
王五

3.2 List集合特有方法

方法名 说明
void add(int index,E element) 在此集合中的指定位置插入指定的元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素

3.3 list集合存储学生对象并遍历

需求:创建一个存储学生对象的集合,存储3个学生对像,使用程序实现在控制台遍历该集合
思路:
①定义学生类
②创建List集合对象
③创建学生对象
④把学生添加到集合
⑤遍历集合(迭代器方式,for循环方式)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//1.创建学生对象
package demo_02;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

//2.测试类
package demo_02;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*List集合特点:
有序:存储和取出的元素顺序一致
可重复:存储的元素可以重复*/

public class ListDemo {
public static void main(String[] args) {
//创建list集合
List<Student> list = new ArrayList<>();

//创建学生对象
Student sc1 = new Student("张三", 18);
Student sc2 = new Student("李四", 19);
Student sc3 = new Student("王五", 10);

//把学生添加到集合
list.add(sc1);
list.add(sc2);
list.add(sc3);

//遍历集合(迭代器方式)
Iterator<Student> it = list.iterator();
while(it.hasNext()){
Student n = it.next();
System.out.println(n.getName()+", "+n.getAge());
}
System.out.println("------------");

//for循环遍历
for (int i = 0;i<list.size(); i++){
Student s = list.get(i);
System.out.println(s.getName()+", "+s.getAge());
}
}
}
//运行结果
张三, 18
李四, 19
王五, 10
------------
张三, 18
李四, 19
王五, 10

3.4 Listlterator

Listlterator:列表迭代器

  • 通过List集合的listlterator()方法得到,所以说它是List集合特有的迭代器
  • 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取巧列表中迭代器的当前位置

Listlterator中的常用方法:

方法名 说明
E next() 返回迭代中的下一个元素
boolean hasNext() 如果迭代具有更多元素,则返回true
E previous() 返回列表中的上一个元素
boolean hasPrevious() 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
void add(E e) 将指定的元素插入列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package listDemo_03;

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class ListIteratorDemo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<S>();

//添加元素
list.add("张三");
list.add("李四");
list.add("王五");

//通过list集合的listIterator()方法得到
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()){
String n = lit.next();
System.out.println(n);
}
System.out.println("----------");

//反向遍历
while (lit.hasPrevious()){
String b = lit.previous();
System.out.println(b);
}
}
}
//运行结果
张三
李四
王五
----------
王五
李四
张三

3.5 增强for循环

增强for:简化数组和Collection集合的遍历

  • 实现Iterable接口的类允许其对象成为增强型for语句的目标
  • 它是DKS之后出现的,其内部原理是一个lterator迭代器

增强for的格式:

1
2
3
4
5
6
7
8
9
10
//格式:
for(元素数据类型变量名:数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}

//范例:
int[] arr={1,2,3,4,5};
for(int i:arr){
System.out.printIn(i)
}

3.6 案例:List集合存储学生对像用三种方式遍历

需求:创建一个存储学生对象的集合,存储3个学生对像,使用程序实现在控制台遍历该集合
思路:
①定义学生类
②创建List集合对象
③创建学生对象
④把学生添加到集合
⑤遍历集合
迭代器:集合特有的遍历方式
普通for:带有索引的遍历方式
增强for:最方使的遍历方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//1.创建
package demo_02;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

//2.测试类
package demo_02;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/*List集合特点:
有序:存储和取出的元素顺序一致
可重复:存储的元素可以重复*/

public class ListDemo {
public static void main(String[] args) {
//创建list集合
List<Student> list = new ArrayList<>();

//创建学生对象
Student sc1 = new Student("张三", 18);
Student sc2 = new Student("李四", 19);
Student sc3 = new Student("王五", 10);

//把学生添加到集合
list.add(sc1);
list.add(sc2);
list.add(sc3);

//遍历集合(迭代器方式)
Iterator<Student> it = list.iterator();
while (it.hasNext()) {
Student n = it.next();
System.out.println(n.getName() + ", " + n.getAge());
}
System.out.println("------------");

//for循环遍历
for (int i = 0; i < list.size(); i++) {
Student s = list.get(i);
System.out.println(s.getName() + ", " + s.getAge());
}
System.out.println("------------");

//增强for循环
for (Student sc : list) {
System.out.println(sc.getName() + ", " + sc.getAge());
}
}
}
//3.运行结果
张三, 18
李四, 19
王五, 10
------------
张三, 18
李四, 19
王五, 10
------------
张三, 18
李四, 19
王五, 10

3.7 数据结构

  • 数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合
  • 通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率

3.8 常见数据结构之栈

  • 数据进入栈模型的过程称为:压/进栈
  • 数据离开栈模型的过程称为:弹/出栈
  • 栈是一种数据先进后出的模型

page_05

3.9 常见数据结构之队列

  • 数据从后端进入队列模型的过程称为:入队列
  • 数据从前端离开队列模型的过程称为:出队列
  • 队列是一种数据先进先出的模型

page_06

3.10 常见数据结构之数组

  • 数组是一种查询快,增删慢的模型
  • 查询数据通过索引定位,查询任意数据耗时相同,查询效率高
  • 删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低
  • 添加数据时,添加位置后的每个数据后移,再添加元素,添加效率极低

3.11 常见数据结构之链表

3.11.1 添加数据

在数据AC之间添加一个数据B,保存在地址54位置

  1. 在数据B对应的下一个数据地址指向数据C
  2. 在数据A对应的下一个数据地址指向数据B

3.11.2 删除数据

在数据AC之间添加一个数据B,保存在地址54位置,删除数据BD之间的数据C

  1. 数据B对应的下一个数据地址指向数据D
  2. 数据C删除

3.11.3 链表查询

  • 查询数据D是否存在,必须从头(head)开始查询
  • 查询第3个数据,必须从头(head)开始查询
  1. 链表是一种增删快的模型(对比数组)
  2. 链表是一种查询慢的模型(对比数组)

3.12 List集合子类特点

List集合常用子类:ArrayList, LinkedList

  • ArrayList::底层数据结构是数组,查询快,增删慢
  • LinkedList:底层数据结构是链表,查询慢,增删快

练习:

分别使用ArrayLista和LinkedList完成存储字符串并遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package myList;

import java.util.ArrayList;
import java.util.LinkedList;

public class ListDemo {
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<String> array= new ArrayList<String>();

array.add("张三");
array.add("李四");
array.add("hello");

//遍历集合
for (String s : array){
System.out.println(s);
}
System.out.println("--------------");

//创建LinkedList集合对象
LinkedList<String> linkedList = new LinkedList<String>();

linkedList.add("hello");
linkedList.add("world");
linkedList.add("java");

//遍历集合
for (String c : linkedList){
System.out.println(c);
}
}
}
//运行结果
张三
李四
hello
--------------
hello
world
java

3.13 案例:ArrayList集合存储学生对象用三种方式遍历

需求:创建一个存储学生对象的集合,存储3个学生对像,使用程序实现在控制台遍历该集合
思路:
①定义学生类
②创建ArrayList集合对像
③创建学生对象
④把学生添加到集合
⑤遍历集合
迭代器:集合特有的遍历方式
普通for:带有索引的遍历方式
增强for:最方便的遍历方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//1.创建学生类
package demo_02;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

//2.测试类(创建ArrayList集合对象)
package demo_02;

import java.util.ArrayList;
import java.util.Iterator;

public class ArrayListDemo {
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<Student> array = new ArrayList<Student>();

//创建学生对象
Student sc1 = new Student("张三", 18);
Student sc2 = new Student("李四", 19);
Student sc3 = new Student("王五", 10);

//把学生添加到集合
array.add(sc1);
array.add(sc2);
array.add(sc3);

//迭代器方式遍历
Iterator<Student> it = array.iterator();
while (it.hasNext()){
Student s = it.next();
System.out.println(s.getName()+", "+ s.getAge());
}
System.out.println("-----------");

//for循环遍历
for (int i = 0; i<array.size(); i++){
Student s1 = array.get(i);
System.out.println(s1.getName()+", "+ s1.getAge());
}
System.out.println("-----------");

//增强for
for (Student s2 : array){
System.out.println(s2.getName()+", "+ s2.getAge());
}
}
}
//运行结果
张三, 18
李四, 19
王五, 10
-----------
张三, 18
李四, 19
王五, 10
-----------
张三, 18
李四, 19
王五, 10

3.14 LinkedList集合的特有功能

方法名 说明
public void addFirst(E e) 在该列表开头插入指定的元素
public void addLast(E e) 将指定的元素追加到此列表的末尾
public E getFirst() 返回此列表中的第一个元素
public E getLast() 返回此列表中的最后一个元素
public E removeFirst() 从此列表中删除并返回第一个元素
public E removeLast() 从此列表中删除并返回最后一个元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package myList;

import java.util.LinkedList;
/*
public void addFirst(E e) 在该列表开头插入指定的元素
public void addLast(E e) 将指定的元素追加到此列表的末尾
public E getFirst() 返回此列表中的第一个元素
public E getLast() 返回此列表中的最后一个元素
public E removeFirst() 从此列表中删除并返回第一个元素
public E removeLast() 从此列表中删除并返回最后一个元素
*/
public class LinkdeListDemo {
public static void main(String[] args) {
//创建LinkdeList集合对象
LinkedList<String> linkdeList = new LinkedList<String>();

linkdeList.add("hello");
linkdeList.add("world");
linkdeList.add("java");

/* public void addFirst(E e) 在该列表开头插入指定的元素
public void addLast(E e) 将指定的元素追加到此列表的末尾*/
linkdeList.addFirst("javase");
linkdeList.addLast("javaee");

/* public E getFirst() 返回此列表中的第一个元素
public E getLast() 返回此列表中的最后一个元素*/
System.out.println(linkdeList.getFirst());
System.out.println(linkdeList.getLast());

/*public E removeFirst() 从此列表中删除并返回第一个元素
public E removeLast() 从此列表中删除并返回最后一个元素*/
System.out.println(linkdeList.removeFirst());
System.out.println(linkdeList.removeLast());
}
}
//运行结果
javase
javaee
javase
javaee

4. set

4.1 set集合的概述和特点

Set集合特点

  • 不包含重复元素的集合
  • 没有带索引的方法,所以不能使用普通for循环遍历

Set集合练习:

  • 存储字符串并遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package demo_01;

/*
Set集合特点
不包含重复元素的集合
没有带索引的方法,所以不能使用普通o循环遍历
HashSet:对集合的迭代顺序不作任何保证
*/

import java.util.HashSet;
import java.util.Set;

public class SetDemo {
public static void main(String[] args) {
//创建集合对象
Set<String> set = new HashSet<String>();

//添加元素
set.add("hello");
set.add("java");
set.add("world");
//不包含重复元素
set.add("java");

//遍历
for (String s : set) {
System.out.println(s);
}
}
}
//运行结果
java
world
hello

4.2 哈希值

哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值

Object类中有一个方法可以获取对象的哈希值

  • public int hashCode():返回对象的哈希码值

对象的哈希值特点

  • 同一个对象多次调用hashCode()方法返回的哈希值是相同的
  • 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//1.
package demo_02;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

/* 重写equals()和hashCode()方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Student student = (Student) o;

if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}

@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
*/
}

//2.
package demo_02;

public class HashDemo {
public static void main(String[] args) {
//创建学生对象
Student s1 = new Student("张三",18);
//同一个对象多次调用HashCode()方法返回的哈希值是相同的
System.out.println(s1.hashCode()); //1239731077
System.out.println(s1.hashCode()); //1239731077

Student s2 = new Student("张三",18);
//默认情况下,不同对象的哈希值不同
//通过方法重写,可以实现不同对象的哈希值相同(重写equals()和hashCode()方法)
System.out.println(s2.hashCode()); //557041912
System.out.println("-----------");

System.out.println("java".hashCode()); //3254818
System.out.println("world".hashCode()); //113318802
System.out.println("java".hashCode()); //3254818
System.out.println("-----------");

System.out.println("重地".hashCode()); //1179395
System.out.println("通话".hashCode()); //1179395
}
}

4.3 HashSet:集合概述和特点

HashSet集合特点:

  • 底层数据结构是哈希表
  • 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以是不包含重复元素的集合

HashSet集合练习:

  • 存储字符串并遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package demo_03;

import java.util.HashSet;

public class HashSetDemo {
public static void main(String[] args) {
//创建集合对象
HashSet<String> hs = new HashSet<String>();

//添加元素
hs.add("hello");
hs.add("world");
hs.add("java");
//set集合,不包含重复的元素
hs.add("world");

//遍历
for (String s : hs) {
System.out.println(s);
}
}
}
//运行结果
world
java
hello

4.4 常见数据结构之哈希表

哈希表

  • JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
  • JDK8以后,在长度比较长的时候,底层实现了优化

4.5 案例:HashSet集合存储学生对像并遍历

需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对像
思路:
①定义学生类
②创建HashSet集合对象
③创建学生对像
④把学生添加到集合
⑤遍历集合(增强for)
⑥在学生类中重写两个方法
hashCode()和equals()
自动生成即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//1.
package demo_03;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

//重写equals()和hashCode()方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Student student = (Student) o;

if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}

@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}

//2.
package demo_03;

import java.util.HashSet;

public class HashSetStuDemo {
public static void main(String[] args) {
//创建集合对象
HashSet<Student> hs = new HashSet<Student>();

//创建学生对象
Student s1 =new Student("张三", 18);
Student s2 =new Student("李四", 20);
Student s3 =new Student("王五", 19);

//重写equals()和hashCode()方法,集合元素不会重复出现
Student s4 =new Student("李四", 20);

//添加学生元素到集合
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);

//遍历
for (Student sc:hs){
System.out.println(sc.getName()+", "+sc.getAge());
}
}
}
//运行结果
王五, 19
张三, 18
李四, 20

4.6 LinkedHashSet:集合概述和特点

LinkedHashSet集合特点

  • 哈希表和链表实现的Set接口,具有可预测的迭代次序
  • 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
  • 由哈希表保证元素唯一,也就是说没有重复的元素

LinkedHashSet:集合练习

  • 存储字符串并遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package demo_04;

import java.util.LinkedHashSet;

public class LinkedHashSetDemo {
public static void main(String[] args) {
//创建集合对象
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();

//添加元素
linkedHashSet.add("hello");
linkedHashSet.add("world");
linkedHashSet.add("java");

//哈希表保证元素的唯一性,也就是说没有重复的元素
linkedHashSet.add("world");

//遍历
for (String s:linkedHashSet){
System.out.println(s);
}
}
}
//运行结果
hello
world
java

4.7 TreeSet集合概述和特点

TreeSet:集合特点:

  • 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法

​ (1) TreeSet():根据其元素的自然排序进行排序

​ (2) TreeSet(Comparator comparator):根据指定的比较器进行排序

  • 没有带索引的方法,所以不能使用普通for循环遍历
  • 由于是Set集合,所以不包含重复元素的集合

TreeSet集合练习:

  • 存储整数并遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package demo_05;

import java.util.TreeSet;

public class TreeSetDemo {
public static void main(String[] args) {
//创建集合对象
TreeSet<Integer> treeSet = new TreeSet<Integer>();
//TreeSet():根据其元素的自然排序进行排序

//添加元素
treeSet.add(10);
treeSet.add(50);
treeSet.add(30);
treeSet.add(20);
treeSet.add(40);

//遍历
for (Integer s : treeSet) {
System.out.println(s);
}
}
}
//运行结果
10
20
30
40
50

4.8 自然排序Comparable的使用

  • 存储学生对像并遍历,创建TreeSet集合使用无参构造方法
  • 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

结论:

  • 用TreeSet集合存储自定义对像,无参构造方法使用的是自然排序对元素进行排序的
  • 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(To)方法
  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//1.学生对象
package demo_05;
//该接口对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的compareTo方法被称为其自然比较方法 。
public class Student implements Comparable<Student>{
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

@Override
public int compareTo(Student s) {
//return 0; 返回0表示元素重复,只会添加第一个元素,不会添加其他元素
//return 1; 按照存储的顺序输出(升序)
//return -1; (降序)
//按照年龄从小到大排序
int num = this.age - s.age; //(升序)
//int num = s.age - this.age;(降序)
//年龄相同时,按照姓名的字母顺序排序
int num2 = num == 0?this.name.compareTo(s.name):num;
return num2;
}
}

//2.测试类
package demo_05;

import java.util.TreeSet;
/*
存储学生对像并遍历,创建TreeSet集合使用无参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
*/
public class TreeSetDemo02 {
public static void main(String[] args) {
//创建集合对象
TreeSet<Student> ts = new TreeSet<Student>();

//创建学生对象
Student s1 = new Student("xishi", 18);
Student s2 = new Student("wangzhaojun", 19);
Student s3 = new Student("diaochan", 20);
Student s4 = new Student("yangyuhuan", 16);

Student s5 = new Student("chenghanhan", 20);
//学生对象添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);

//遍历
for (Student s : ts) {
System.out.println(s.getName() + ", " + s.getAge());
}
}
}
//运行结果
yangyuhuan, 16
xishi, 18
wangzhaojun, 19
chenghanhan, 20
diaochan, 20

4.9 比较器排序Comparator的使用

  • 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
  • 要求:按照年龄从小到大排序,年龄相同时,按姓名的字母顺序排序

结论:

  • 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
  • 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(To1,To2)方法
  • 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//1.创建学生类
package demo_06;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}
}

//2.测试类
package demo_06;

import java.util.Comparator;
import java.util.TreeSet;
/*
- 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按姓名的字母顺序排序
*/
public class TreeSetDemo {
public static void main(String[] args) {
//创建集合对象
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {//创建匿名对象
@Override
public int compare(Student o1, Student o2) {
//按照年龄从小到大排序
int num = o1.getAge() - o2.getAge();
//年龄相同时,按姓名的字母顺序排序
int num2 = num == 0?o1.getName().compareTo(o2.getName()):num;
return num2;
}
});

//创建学生对象
Student s1 = new Student("xishi", 18);
Student s2 = new Student("wangzhaojun", 19);
Student s3 = new Student("diaochan", 20);
Student s4 = new Student("yangyuhuan",22);

Student s5 = new Student("chenghanhan", 20);
//学生对象添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);

//遍历
for (Student s : ts) {
System.out.println(s.getName() + ", " + s.getAge());
}
}
}
//运行结果
xishi, 18
wangzhaojun, 19
chenghanhan, 20
diaochan, 20
yangyuhuan, 22

4.10 案例:成绩排序

  • 需求:用TreeSet:集合存储多个学生信息(姓名,语文成绩,数学成绩,并遍历该集合
  • 要求:按照总分从高到低出现

思路:

①定义学生类
②创建TreeSet集合对象,通过比较器排序进行排序
③创建学生对象
④把学生对象添加到集合
⑤遍历集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//1.创建学生类
package demo_07;

public class Student {
private String name;
private int chinese;
private int math;

public Student() {
}

public Student(String name, int chinese, int math) {
this.name = name;
this.chinese = chinese;
this.math = math;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getChinese() {
return chinese;
}

public void setChinese(int chinese) {
this.chinese = chinese;
}

public int getMath() {
return math;
}

public void setMath(int math) {
this.math = math;
}

public int sum(){ //求和方法
return chinese+math;
}
}

//2.测试类
package demo_07;

import java.util.Comparator;
import java.util.TreeSet;
/*
- 需求:用TreeSet:集合存储多个学生信息(姓名,语文成绩,数学成绩,并遍历该集合
- 要求:按照总分从高到低出现
*/
public class TreeSetDemo {
public static void main(String[] args) {
//创建集合对象,通过比较器排序进行排序
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.sum() - o2.sum();
int num2 = num == 0?o1.getName().compareTo(o2.getName()):num;
return num2;
}
});

//创建学生对象
Student s1 = new Student("张三",98,99);
Student s2 = new Student("李四",95,95);
Student s3 = new Student("王五",95,99);
Student s4 = new Student("小陈",98,100);
Student s5 = new Student("小尚",100,99);

Student s6 = new Student("逸乐",95,99);
//添加学生对象到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);

//遍历
for (Student s:ts){
System.out.println(s.getName()+", "+s.getChinese()+", "+s.getMath()+", "+s.sum());
}
}
}
//运行结果
李四, 95, 95, 190
王五, 95, 99, 194
逸乐, 95, 99, 194
张三, 98, 99, 197
小陈, 98, 100, 198
小尚, 100, 99, 199

4.11 案例:不重复的随机数

需求:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出

思路:

①创建Set集合对象
②创建随机数对象
③判断集合的长度是不是小于10
是:产生一个随机数,添加到集合
回到3继续
④遍历集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package demo_07;

import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

public class SetDemo {
public static void main(String[] args) {
//创建集合对象
//Set<Integer> set = new HashSet<Integer>();
Set<Integer> set = new TreeSet<Integer>();

//创建随机数对象
Random r = new Random();

//判断集合长度是否小于10
while (set.size() < 10) {
int num = r.nextInt(20) + 1;
set.add(num);
}

//遍历
for (Integer i : set) {
System.out.println(i);
}
}
}