异常

异常体系

image-20221021012940638

1
2
3
4
5
6
7
8
Throwable	//异常体系的最顶层类
Error
Exception
非RunTimeExceptionException
RuntimeException
Java 把所有的非正常的情况分为两种:异常(Exception) 和错误(Error),他们都继承 Throwable 父类。

Error 错误,一般指的是与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断结束,所以应用程序不应该试图去 catch 捕获 Error对象。

JVM默认处理异常的方式: 直接打印在控制台, 抛出来, 后续代码不在执行

处理异常方式:

方式一: 自己处理: try.catch.finally

特点: 处理完后, 程序会继续向下执行.

1
2
3
4
5
6
7
8
//格式
try{
//业务实现的代码
} catch(Exception e) {
e.printStackTrace()
} finally{
//回收资源,这里总会被执行。
}

Demo(测试类)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Demo16_异常处理 {
// 针对运行期异常, 一般建议都是整体捕获操作, 捕获掉之后, 可以选择处理异常, 也可以选择捕获后抛出
public static void main(String[] args) {
try {
System.out.println("1111");
System.out.println("222");
System.out.println("333");

double x = 1 / 0; // 除 0 异常

System.out.println("444");
System.out.println("555");
} catch (Exception e){
// 处理异常 : 方式一 直接处理, 通知相关的人员 方式二, 可以选择抛出
System.out.println("处理异常内容");

// 捕获后, 抛出
// throw new Exception();
}finally {
System.out.println("一定会运行的代码");
}
}
}

方式二: 抛出异常

特点: 处理完后, 程序会终止执行.

1
2
//格式
throws 异常的类型; //该内容是写到方法的形参列表之前的.

Demo(测试类)

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Demo17_异常处理 {
// 针对编译期异常, 可以直接选择抛出异常处理模式 当然也可以捕获
public static void main(String[] args) throws ParseException {
SimpleDateFormat format1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
// 编译期异常解决方案: 思考 我是否会出现这个异常呢? 如果不会 直接选择抛出或者 程序有最终异常处理方案 直接抛出
Date date = format1.parse("2022/05/03 12:14:20");
System.out.println(date);
}
}

集合

集合体系介绍

image-20221022232536817

1
2
3
4
5
6
7
8
9
10
记忆
集合的顶层都是接口, 其中Collection接口是单列集合的顶层接口, Map接口是双列集合的顶层接口

Collection接口(单列集合)有两大子体系:
1.List体系的特点是: 有序, 可重复
2.Set体系的特点是: 无序, 唯一

一个小技巧: 以后但凡我们学习一个新的体系时, 都建议采用学顶层, 用底层的方式来学习.

解释: 因为顶层封装的是整个继承体系的共性内容, 而底层才是具体的实现, 体现.

Collection常用方法

1
2
3
4
5
6
7
8
9
10
11
public boolean add(E e) 添加元素.
public boolean remove(Object obj) 从集合中移除指定的元素.
public void clear() 清空集合对象
public boolean contains(Object obj) 判断集合中是否包含指定的元素
public boolean isEmpty() 判断集合是否为空
public int size() 获取集合的长度, 即集合中元素的个数
public Iterator<E> iterator() //根据集合对象, 获取其对应的迭代器对象.

Iterator迭代器中的方法:
public boolean hasNext() //判断迭代器中是否还有下一个元素.
public E next() //获取迭代器中的下一个元素.

List集合

List集合的元素特点是: 有序, 可重复, 元素有索引.

  1. 有序: 指的是元素的存储顺序和取出顺序是一致的.
  2. 可重复: 指的是List集合可以存储重复的元素.
  3. 元素有索引: 指的是List集合中每个元素都是由索引的, 且索引是从0开始的.

相关的方法:

1
2
3
4
5
6
7
8
public void add(int index, E element)
解释: 在集合的指定位置(索引), 插入指定的元素, 索引越界会报IndexOutOfBoundsException异常.
public E remove(int index)
解释: 删除指定索引处的元素, 并返回被删除的元素, 索引越界会报IndexOutOfBoundsException异常.
public E set(int index, E element)
解释: 修改指定索引处的元素为指定的值, 并返回修改前的元素, 索引越界会报IndexOutOfBoundsException异常.
public E get(int index)
解释: 根据索引, 获取其对应的元素, 索引越界会报IndexOutOfBoundsException异常.

List集合是一个接口, 其常用子类主要有两个, 分别为ArrayList, LinkedList

1
2
3
4
1.ArrayList集合的特点: 底层数据结构是数组, 查询和修改快, 增删慢.
2.LinkedList集合的特点: 底层数据结构是链表, 查询和修改慢, 增删快.

注意: 它们的相同点是, 都是有序的, 而且可以存储重复元素.

CollectAPI常用使用方式

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
import java.util.ArrayList;
import java.util.List;

public class Demo01_ArrayList {

public static void main(String[] args) {

// 需求: 创建一个集合, 尝试添加集合, 获取集合元素, 遍历集合等操作

List<String> list1 = new ArrayList<>();

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

//2. 获取元素
System.out.println(list1.get(0));
System.out.println(list1.get(1));
System.out.println(list1.get(2));

//3. 判断某个元素是否存在

System.out.println(list1.contains("张三")); // 判断某个元素是否存在, 如果存在 返回true

//4. 判断集合是否为空集合
System.out.println(list1.isEmpty()); // 判断集合是否是一个空集合, 如果是true, 如果不是 返回false

// 5. 获取集合的长度
System.out.println(list1.size());

//3. 删除元素
Boolean b = list1.remove("李四"); // 如果删除成功, 返回true 否则返回False 删除指定的元素
System.out.println(b);

String reEl = list1.remove(0); // 根据索引删除元素, 返回删除的元素
System.out.println(reEl);

//4. 清空元素
list1.clear();
System.out.println(list1);
}
}

Demo(测试类)-测试创建集合/往集合中添加元素/遍历List集合

需求:

  • 定义一个学生类, 属性为姓名和年龄.
  • 创建List集合(linkedList), 用来存储学生对象.
  • 往List集合中, 添加3个学生的信息. (演示队列的特性)
  • 遍历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
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
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class Demo02_Student_LinkedList {

public static void main(String[] args) {

//1. 创建 LinkedList, 其泛型: Student
// 是一个队列 而且还是双端队列, 队列具备特性: FIFO
//List<Student> list = new LinkedList<Student>();
LinkedList<Student> list = new LinkedList<Student>();

//2. 添加元素:
list.offerFirst(new Student("张三",20));
list.offerFirst(new Student("李四",18));
list.offerLast(new Student("王五",22));

list.add(1,new Student("赵六",25));


//3. 获取元素内容
System.out.println(list);
Student stu = list.get(0);
System.out.println(stu);

System.out.println("-----------------");
//4. 遍历集合
// 4.1 基于迭代器遍历
Iterator<Student> stuIter = list.iterator();
// hasNext : 判断是否还有下一个, 有返回true
while( stuIter.hasNext() ){
// 获取下一个元素, 不断的执行, 不断的往下获取
Student s = stuIter.next();
System.out.println(s);
}
System.out.println("-----------------");
// 4.2 增强for循环
for (Student student : list) {
System.out.println(student);
}
System.out.println("-----------------");
// 4.3 普通for循环
for(int i = 0; i< list.size() ; i++){

System.out.println(list.get(i));
}
System.out.println("-----------------");
// 5. 如何删除元素: 模拟队列
// 从右侧弹出
//Student s1 = list.pollLast();
//Student s2 = list.pollLast();
//Student s3 = list.pollLast();
//Student s4 = list.pollLast();

// 从左侧弹出
//Student s1 = list.pollFirst();
//Student s2 = list.pollFirst();
//Student s3 = list.pollFirst();
//Student s4 = list.pollFirst();

//System.out.println(s1);
//System.out.println(s2);
//System.out.println(s3);
//System.out.println(s4);
}
}

Set集合

Set集合是Collection集合的子体系, 它的元素特点是无序, 唯一.

注意:

  • Set集合是一个接口, 所以不能通过new的方式直接创建它的对象.
  • Set集合中没有带索引的方法, 所以不能通过普通for循环遍历.
  • Set集合的常用子类主要是HashSet集合

HashSet集合:

1
2
3
4
5
6
7
8
9
10
1.底层数据结构是哈希表.
2.对集合的迭代顺序不做任何保证, 也就是说不保证元素的存取顺序一致.
3.没有带索引的方法, 所以不能通过普通for循环遍历.
4.由于是Set集合, 所以是不包含重复元素的集合.

总结:
HashSet集合的特点是: 无序, 唯一, 元素无索引, 它的底层数据结构是: 哈希表.

扩展:
所谓的哈希值指的是JDK根据对象的地址, 或者字符串, 或者数字 算出来的int类型的数值.

Demo 测试类1

需求1:

  • 1 定义HashSet集合, 存储字符串”hello”, “world”, “java”, “world”
  • 2 遍历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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.itheima.collection.set;

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

public class Demo03_HashSet {
public static void main(String[] args) {

//1. 创建HashSet集合 : 无序 去重
Set<String> set = new HashSet<>();

//2. 执行相关的操作
//2.1 添加数据
set.add("hello");
set.add("world");
set.add("java");
set.add("world");

//2.2 打印set集合的数据
System.out.println(set);
// 增强for循环
for (String s : set) {
System.out.println(s);
}
System.out.println("-------------");
// 迭代器方案
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()){

System.out.println(iterator.next());
}

// 2.3 判断某个元素是否存在
System.out.println(set.contains("java")); // 如果存在 返回true
//2.4 判断集合是否为空
System.out.println(set.isEmpty()); // 如果为空返回true

// 2.5 获取集合的长度
System.out.println(set.size());

// 2.6 删除元素
Boolean flag = set.remove("world"); // 删除某个元素, 如果为true表示删除成功
System.out.println(flag);

System.out.println(set);

}
}

Demo测试类2

需求2:

  • 1 定义学生类, 属性为姓名和年龄.
  • 2 创建HashSet集合, 用来存储学生对象, 并往其中添加3个学生的信息.
  • 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
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
student类:

package com.itheima.collection.list;

import java.util.Objects;

public class Student {
public Student() {
}

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

private String name;
private Integer 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 boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) &&
Objects.equals(age, student.age);
}
// 计算hash值, 也是计算 其内容的hash值, 而非对象的hash值
@Override
public int hashCode() {

return Objects.hash(name, age);
}

@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}


测试类:
package com.itheima.collection.set;

import com.itheima.collection.list.Student;

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

public class Demo04_Student_set {
public static void main(String[] args) {

//1. 创建set集合
Set<Student> studentSet = new HashSet<>();

//2. 添加元素
studentSet.add(new Student("张三",10));
studentSet.add(new Student("李四",18));
studentSet.add(new Student("王五",20));
studentSet.add(new Student("赵六",21));
studentSet.add(new Student("赵六",21));

// 发现事情: 如果添加两个相同内容的student对象, 希望能够去重, 但是实际并没有
// 为甚没呢? 因为都是new操作, 都是一个新对象, 所以自然不能放置在一起, 默认比较的是地址值
// 如果解决呢? 通过重写 equals 以及 重写 hashCode方法 重写后, 可以确保对象的唯一性

//3. 遍历数据
for (Student student : studentSet) {
System.out.println(student);
}
}
}

哈希表

  • JDK8以前, 底层采用数组 + 链表的形式实现, 可以理解为: 一个元素为链表的数组.
  • JDK8以后, 在长度比较长的时候, 底层实现了优化.

双列集合

Map集合是双列集合的顶层接口, 它是用来存储键值对对象的, 其中键具有唯一性, 而值是可以重复的. 类似于Python中字典

即: Map集合的数据结构只针对于有效.

因为Map是接口, 不能通过new关键字直接创建它的对象, 我们可以通过多态的形式, 创建其子类对象. 从而实现创建Map集合对象的这个需求.

注意: Map集合的常用子类是: HashMap

常用的成员方法:

方法名 说明
V put(K key,V value) 添加元素
V remove(Object key) 根据键删除键值对元素
void clear() 移除所有的键值对元素
boolean containsKey(Object key) 判断集合是否包含指定的键
boolean containsValue(Object value) 判断集合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中键值对的个数

Map集合的获取功能:

方法名 说明
V get(Object key) 根据键获取值
Set keySet() 获取所有键的集合
Collection values() 获取所有值的集合

Demo01

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
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Demo05_HashMap {
public static void main(String[] args) {

//1. 创建HashMap集合
Map<String,Object> hashMap = new HashMap<String,Object>();

//2. 执行相关的操作
//2.1: 添加数据 put
hashMap.put("name","张三");
hashMap.put("age",20);
hashMap.put("address","北京");

//2.2 获取数据:
// 根据key获取value
System.out.println(hashMap.get("name"));
// 遍历操作:
System.out.println("-------------");
// 方式一: 获取所有key, 然后根据key获取value
Set<String> keys = hashMap.keySet();
for (String key : keys) {
System.out.println( key+":"+ hashMap.get(key));
}
System.out.println("-------------");
// 方式二:直接基于增强for : 获取所有的value 遍历value值
for (Object v : hashMap.values()) {
System.out.println(v);
}

//2.3 判断某一个key是否存在
System.out.println(hashMap.containsKey("name")); // true 表示存在
// 2.4 判断某一个value是否存在
System.out.println(hashMap.containsValue("北京")); // true表示存在
// 2.5 判断map是否为空
System.out.println(hashMap.isEmpty()); // true 表示map是一个空集合
// 2.6 获取map长度
System.out.println(hashMap.size());
// 2.7 删除元素
Object val = hashMap.remove("name"); // 返回删除对应的value值, 如果没有 为 null
System.out.println(val);

boolean flag = hashMap.remove("age", 20); // true 表示删除成功
System.out.println(flag);
}
}

Demo02 - 放置对象

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
import com.itheima.collection.list.Student;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Demo05_student_map {
public static void main(String[] args) {

//1. 创建HashMap集合: 一般都是 key为 string value可以是任意类型
Map<String,Student> studentMap1 = new HashMap<String,Student>();
Map<Student,String> studentMap2 = new HashMap<Student,String>();
//2. 添加数据
studentMap1.put("s01",new Student("张三",20));
studentMap1.put("s02",new Student("李四",20));

studentMap2.put(new Student("张三",20),"s01");
studentMap2.put(new Student("李四",20),"s02");

//3. 打印数据
System.out.println(studentMap1);
System.out.println(studentMap2);

}
}

Collections集合工具类

Collections类是针对集合操作的工具类.

  • 常用方法
方法名 说明
public static void sort(List list) 将指定的列表按升序排序
public static void reverse(List<?> list) 反转指定列表中元素的顺序
public static void shuffle(List<?> list) 使用默认的随机源随机排列指定的列表

Demo(测试类-演示相关方法)

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
import com.itheima.collection.list.Student;

import java.util.*;

public class Demo06_collections {
public static void main(String[] args) {

//1. 创建一个空集合
List<Integer> list = new ArrayList<>();
//List<Integer> list = Collections.emptyList(); 不可变的
//Set<Student> set = Collections.emptySet(); 不可变的
// Map<String,String> map = Collections.emptyMap(); 不可变的

//2. 添加数据
list.add(20);
list.add(30);
list.add(15);
list.add(18);
list.add(50);

System.out.println(list);


//3. 执行排序操作
//Collections.sort(list);
// 参数2: 比较器 compare 比较的方法: 传入相邻的两个元素进行比较
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// 升序: A > B ? 正数: 负数 || A < B ? 负数 : 正数 倒序: A > B ? 负数 : 正数 || A < B ? 正数: 负数
return o1 < o2 ? 1: -1;
}
});

System.out.println(list);

// 4- 反转操作
Collections.reverse(list);
System.out.println(list);

// 5- shuffle打散
Collections.shuffle(list);
System.out.println(list);

}
}

可变参数

如果遇到让我们定义一些方法, 分别获取2个整数, 3个整数, 4个整数的和, 此时我们只能通过方法重载的形式来实现, 但是这样做比较繁琐, 我们发现上述的这些方法, 只有参数列表是变化的, 那能不能优化这个问题呢?

肯定是可以的, 我们可以通过可变参数来优化这个问题.

可变参数又称参数个数可变,它用作方法的形参出现,那么方法参数个数就是可变的了

格式:

1
2
3
4
5
6
修饰符 返回值类型 方法名(数据类型… 变量名) {  }


说明:
可变参数的底层就是一个数组.
方法的形参列表有且只能有一个可变参数, 并且可变参数要放到形参列表的最后.

Demo(测试类)

需求:

  • 1- 定义getSum()方法, 用来获取n个整数的和(n可能是任意的一个数字).
  • 2- 在main方法中, 调用getSum()方法.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.itheima.collection.可变参数;

public class Demo07_可变参数 {

public static void main(String[] args) {

// 调用getSum()方法:
Demo07_可变参数 demo07 = new Demo07_可变参数();
Integer sum = demo07.getSum(5,3,7,5);
System.out.println(sum);

}
// 可变参数本质上就是一个数组
public Integer getSum(Integer... num){

Integer sum = 0;
for (Integer n : num) {
sum += n;
}
return sum;
}
}

Lambda表达式

Lambda表达式初体验

需求:

  • 1- 已知接口Animal中有一个抽象方法eat()
  • 2- 在测试类AnimalTest中定义show(Animal an)方法, 实现调用Animal#eat()方法.
  • 3- 并在main方法中, 调用AnimalTest#show()方法.

Demo(测试类)

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
public class EatableDemo {
public static void main(String[] args) {
//直接实例化一个类
Eatable cat = new Cat();
useEatable(cat);
//使用匿名内部类
useEatable(new Eatable() {
@Override
public void eat() {
System.out.println("狗吃狗粮");
}
});
//lambda 表达式实现 eat() 方法
useEatable(
//(参数列表)->{具体实现}
//重写的是 eat() 无参构造方法
() -> {
System.out.println("熊猫吃竹子");
}
);
}

public static void useEatable(Eatable e){
e.eat();
}
}

Lambda表达式的标准格式

格式:

1
(形式参数) -> {代码块}
  • 形式参数:如果有多个参数,参数之间用逗号隔开, 如果没有参数,留空即可

  • ->:由英文中画线和大于符号组成,固定写法。代表指向动作

  • 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容

  • 组成Lambda表达式的三要素:形式参数,箭头,代码块

使用的前提条件: 有一个接口, 且接口中有且仅有一个抽象方法.

Demo01(无参无返回值抽象方法)

需求:

定义一个接口(Eatable),里面定义一个抽象方法:void eat();
定义一个测试类(EatableDemo),在测试类中提供两个方法
一个方法是:useEatable(Eatable e)
一个方法是主方法,在主方法中调用useEatable方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public interface Eatable {
public void eat();
}


测试类:
package com.itheima.lambda;

public class Demo08_lambda_Eatable {
public static void main(String[] args) {
Demo08_lambda_Eatable demo08 = new Demo08_lambda_Eatable();
// 以后书写就是这一块内容, 框架提供了支持传递lambda表达式的方法, 我们在调用的时候, 传递lambda即可
demo08.useEatable( () -> {
int i = 10;
System.out.println("我要吃东西,吃"+i +"份");
} );

}

public void useEatable(Eatable e) {
e.eat();
}
}

Demo02(有参无返回值抽象方法)

需求

定义一个接口(Flyable),里面定义一个抽象方法:void fly(String s);
定义一个测试类(FlyableDemo),在测试类中提供两个方法
一个方法是:useFlyable(Flyable f)
一个方法是主方法,在主方法中调用useFlyable方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public interface Flyable {

public void fly(String s);
}

测试:

package com.itheima.lambda;

public class Demo09_lambda_Flyable {
public static void main(String[] args) {
// 调用方法
useFlyable((String s) -> {
System.out.println(s +": 想飞");
});
// 简单写法:
useFlyable( s -> System.out.println(s +": 想飞") );
}

public static void useFlyable(Flyable f){
f.fly("张三");
}

}

Demo03(有参有返回值抽象方法)

需求:

定义一个接口(Addable),里面定义一个抽象方法:int add(int x,int y);
定义一个测试类(AddableDemo),在测试类中提供两个方法
一个方法是:useAddable(Addable a)
一个方法是主方法,在主方法中调用useAddable方法

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
public interface Addable {
public int add(int x , int y);
}




public class Demo10_lambda_Addable {
public static void main(String[] args) {
// 调用方法
useAddable( (int x,int y) -> {
return x + y;
} );

// 简写:
useAddable( (x,y) -> x + y );
}

public static void useAddable(Addable a){

int sum = a.add(3,5);
System.out.println(sum);
}

}

Demo04(模拟一下Spark中map方法: 传入一个返回一个操作)

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
public interface SparkRDD<IN,OUT> {
public OUT map(IN data);

}

测试:
package com.itheima.lambda;

import java.util.Arrays;

public class Demo11_lambda_SparkRDD {
public static void main(String[] args) {
Demo11_lambda_SparkRDD rdd = new Demo11_lambda_SparkRDD();
String[] lineS = rdd.map( line -> line.split(" ") );
System.out.println(Arrays.toString(lineS));
}

public String[] map(SparkRDD<String,String[]> sparkRDD){

String[] lineS = sparkRDD.map("hadoop hive hadoop hive hadoop sqoop");

//System.out.println(Arrays.toString(lineS));
return lineS;

}
}

Lambda省略模式

规则:

  • 参数类型可以省略。但是有多个参数的情况下,不能只省略一个
  • 如果参数有且仅有一个,那么小括号可以省略
  • 如果代码块的语句只有一条,可以省略大括号和分号,和return关键字

Demo(测试类)

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
public interface Addable {
int add(int x, int y);
}

public interface Flyable {
void fly(String s);
}

public class LambdaDemo {
public static void main(String[] args) {
// useAddable((int x,int y) -> {
// return x + y;
// });
//参数的类型可以省略
useAddable((x, y) -> {
return x + y;
});

// useFlyable((String s) -> {
// System.out.println(s);
// });

//如果参数有且仅有一个,那么小括号可以省略
// useFlyable(s -> {
// System.out.println(s);
// });

//如果代码块的语句只有一条,可以省略大括号和分号
useFlyable(s -> System.out.println(s));

//如果代码块的语句只有一条,可以省略大括号和分号,如果有return,return也要省略掉
useAddable((x, y) -> x + y);
}
private static void useFlyable(Flyable f) {
f.fly("风和日丽,晴空万里");
}
private static void useAddable(Addable a) {
int sum = a.add(10, 20);
System.out.println(sum);
}

Lambda表达式和匿名内部类的区别

  • 所需类型不同
    • 匿名内部类:可以是接口,也可以是抽象类,还可以是具体类
    • Lambda表达式:只能是接口
  • 使用限制不同
    • 如果接口中有且****仅有一个抽象方法****,可以使用Lambda表达式,也可以使用匿名内部类
    • 如果接口中多于一个抽象方法,只能使用匿名内部类,而不能使用Lambda表达式
  • 实现原理不同
    • 匿名内部类:编译之后,产生一个单独的.class字节码文件
    • Lambda表达式:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成。

JDBC

简介

JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API。JDBC是Java访问数据库的标准规范,可以为不同的关系型数据库提供统一访问,它由一组用Java语言编写的接口和类组成。

JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。 今天我们使用的是mysql的驱动mysql-connector-java-5.1.37-bin.jar

JDBC规范(掌握四个核心对象):

  • 1 DriverManager:用于注册驱动
  • 2 Connection: 表示与数据库创建的连接
  • 3 Statement: 操作数据库sql语句的对象
  • 4 ResultSet: 结果集或一张虚拟表

JDBC使用步骤

JDBC规范的 操作步骤:
0. 导入驱动. 连接数据库, 就导入对应的驱动, 只要做一次就行了.
1. 注册驱动.
2. 获取连接对象.
3. 获取平台对象(即: 可以执行SQL语句的对象)
4. 执行SQL语句, 获取结果集.
5. 操作结果集.
6. 释放资源.

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
JDBC使用规范步骤 : 6大步
1- 注册驱动: Class.forName("com.mysql.jdbc.Driver");
2- 获取连接: Connection conn = DriverManager.getConnection(url,username,password);
参数1: url路径地址
格式: jdbc:数据库名称://host:port/数据库名
参数2: 用户名
参数3: 密码
3- 创建语句执行平台:
方式一: Statement stat = conn.createStatement()
方式二: PreparedStatement stat = conn.prepareStatement(String sql) 预编译语句执行平台
4- 执行SQL:
执行增 删 改:
Boolean stat.execute(sql) 配合方式一 返回false 表示执行增删改 返回true表示执行select
int executeUpdate(String sql) 配合方式一 返回影响了多少行

boolean execute() 配合方式二 返回false 表示执行增删改 返回true表示执行select
int executeUpdate() 配合方式二 返回影响了多少行
setXXX(int parameterIndex, Xxx x); Xxx 表示某种数据类型 比如 setInt() 配合方式二

查询操作:
ResultSet executeQuery(String sql) ; 返回的结果集 ResultSet(二维表)
5- 处理结果集
ResultSet相关的API:
boolean next() ; 用于指向下一行 如果没有下一行了, 返回false
getXxx('字段名'| 第几列); Xxx 表示数据类型 用于获取对应列的数据

6- 释放资源: 把对象中含有close方法的对象,全部关闭, 遵循 从后往前依次关闭

Demo(查询测试类)

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
public class Demo01 {
public static void main(String[] args) throws Exception {
//1. 注册驱动.
//方式1: 手动注册, 这种方式可以注册驱动, 但是会使得驱动注册两次. 我们不用.
//DriverManager.registerDriver(new Driver());

//方式2: 反射注册驱动, 相当于把该类的字节码文件直接加载到内存, 类中的静态代码块会随着类的加载而直接加载.
//Class.forName("com.mysql.jdbc.Driver"); //MySQL5.X的写法.
Class.forName("com.mysql.cj.jdbc.Driver"); //MySQL8.X的写法.

//2. 获取连接对象.
//参数1: 数据库连接字符串, 格式为: jdbc:mysql://ip:端口号/要操作的具体的数据库 参数2: 要连接到的数据库的账号. 参数3: 要连接到的数据库的密码.
//Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/day01", "root", "123456");
//Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day01", "root", "123456");
//如果连接到的是 本机数据库, 则: IP和端口号可以省略不写. MySQL8.X要加两个参数, 即: serverTimezone: 设置时区. useSSL=false 关闭SSL协议校验. MySQL5.X不需要写这两个参数.
Connection conn = DriverManager.getConnection("jdbc:mysql:///day01?serverTimezone=UTC&useSSL=false", "root", "123456");

//3. 获取平台对象(即: 可以执行SQL语句的对象)
Statement stat = conn.createStatement();

//4. 执行SQL语句, 获取结果集.
//String sql = "select name, id, salary, deg, dept from employee;"; //根据SQL语句不同, 返回的列的编号也不一样.
String sql = "select * from employee;";
ResultSet rs = stat.executeQuery(sql);

//5. 操作结果集.
while (rs.next()) { //rs.next() 判断结果集中是否有下1行元素, 有: true, 没有:false 类似于迭代器的hasNext()方法.
//方式1: 根据列的编号(从1开始数)获取该列的值.
/*int id = rs.getInt(1);
String name = rs.getString(2);*/

//方式2: 根据列名获取.
int id = rs.getInt("id");
String name = rs.getString("name");
String deg = rs.getString("deg");
int salary = rs.getInt("salary");
String dept = rs.getString("dept");

//打印读取到的内容.
System.out.println(id + ", " + name + ", " + deg + ", " + salary + ", " + dept);
}

//6. 释放资源.
rs.close(); //结果集对象.
stat.close(); //平台对象(执行SQL语句的)
conn.close(); //连接对象
}
}

Demo(增删查测试类)

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
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

/*
JDBC案例: 更新操作.
*/
public class Demo02 {
public static void main(String[] args) throws Exception {
//1. 注册驱动.
Class.forName("com.mysql.cj.jdbc.Driver");

//2. 获取连接对象.
Connection conn = DriverManager.getConnection("jdbc:mysql:///day01?serverTimezone=UTC&useSSL=false", "root", "123456");

//3. 获取平台对象(即: 可以执行SQL语句的对象)
Statement stat = conn.createStatement();

//4. 执行SQL语句, 获取结果集.
//String sql_insert = "insert into employee values(1207, '乔峰', '入门弟子', -100, '业务部');";
//String sql_update = "update employee set deg ='帮主', salary=6666666 where id = 1207;";
String sql_delete = "delete from employee where id = 1207;";

int i = stat.executeUpdate(sql_delete); //执行更新语句(增删改), 返回: 受影响的行数.

//5. 操作结果集.
System.out.println(i != 0 ? "操作成功" : "操作失败");

//6. 释放资源.
stat.close(); //平台对象
conn.close(); //连接对象

}
}