文章目录
- day04_Java高级
-
- 一、今日课程内容
- 二、可变参数
- 三、Java的集合
-
- 1、单列集合
-
- [1.1 List集合](#1.1 List集合)
- [1.2 常见的数据结构(了解)](#1.2 常见的数据结构(了解))
- [1.3 Set集合](#1.3 Set集合)
- [1.4 哈希表](#1.4 哈希表)
- 2、双列集合
- 3、Collections集合工具类
- 四、(掌握)Lambda表达式
- 五、JDBC协议
-
- 1、JDBC原理
- 2、JDBC入门案例
-
- [2.1 查询表中数据](#2.1 查询表中数据)
- [2.2 如何添加数据](#2.2 如何添加数据)
- [2.3 如何修改数据](#2.3 如何修改数据)
- [2.4 如何删除数据](#2.4 如何删除数据)
day04_Java高级
一、今日课程内容
- 可变参数(熟悉)
- Java的集合(掌握)
- lambda表达式(掌握)
- JDBC的协议(熟悉,JavaEE的框架)
二、可变参数
如果遇到让我们定义一些方法, 分别获取2个整数, 3个整数, 4个整数的和, 此时我们只能通过方法重载的形式来实现, 但是这样做比较繁琐, 我们发现上述的这些方法, 只有参数列表是变化的, 那能不能优化这个问题呢?
肯定是可以的, 我们可以通过可变参数来优化这个问题.
可变参数又称参数个数可变,它用作方法的形参出现,那么方法参数个数就是可变的了
格式:
sql
修饰符 返回值类型 方法名(形参1,形参2,数据类型... 变量名) { }
说明:
可变参数的底层就是一个数组.
方法的形参列表有且只能有一个可变参数, 并且可变参数要放到形参列表的最后.
需求:
- 1- 定义getSum()方法, 用来获取n个整数的和(n可能是任意的一个数字).
- 2- 在main方法中, 调用getSum()方法.
java
package com.itheima.day04;
public class 可变参数 {
public static void main(String[] args) {
System.out.println(getSum("a",1, 2));
System.out.println(getSum("a",1, 2, 3));
System.out.println(getSum("a",1, 2, 3, 4, 5, 6, 7));
}
/*
可变参数有两个注意事项:
1- 可变参数只允许放在参数列表的最末尾
2- 一个方法的形参中,只允许最多有一个可变参数
*/
public static int getSum(String name,int... nums){
System.out.println(nums.length);
int result = 0;
for (int num : nums) {
result += num;
}
return result;
}
// public static int getSum(int num1,int num2){
// int result = num1 + num2;
// return result;
// }
//
// public static int getSum(int num1,int num2,int num3){
// int result = num1 + num2 + num3;
// return result;
// }
}
三、Java的集合
Python中List、Set、Dict
集合体系图:
sql
记忆
集合的顶层都是接口, 其中Collection接口是单列集合的顶层接口, Map接口是双列集合的顶层接口
Collection接口(单列集合)有两大子体系:
1.List体系的特点是: 有序, 可重复
2.Set体系的特点是: 无序, 唯一
一个小技巧: 以后但凡我们学习一个新的体系时, 都建议采用学顶层, 用底层的方式来学习.
解释: 因为顶层封装的是整个继承体系的共性内容, 而底层才是具体的实现, 体现.
1、单列集合
集合是用来存储多个同类型 数据的容器, 它的长度是可以变化的.
collection常用方法如下:
sql
1.public boolean add(E e) 添加元素.
2.public boolean remove(Object obj) 从集合中移除指定的元素.
3.public void clear() 清空集合对象
4.public boolean contains(Object obj) 判断集合中是否包含指定的元素
5.public boolean isEmpty() 判断集合是否为空
6.public int size() 获取集合的长度, 即集合中元素的个数
7.public Iterator<E> iterator() //根据集合对象, 获取其对应的迭代器对象.
Iterator迭代器中的方法:
public boolean hasNext() //判断迭代器中是否还有下一个元素.
public E next() //获取迭代器中的下一个元素.
1.1 List集合
List集合的元素特点是: 有序, 可重复, 元素有索引.
- 有序: 指的是元素的存储顺序和取出顺序是一致的.
- 可重复: 指的是List集合可以存储重复的元素.
- 元素有索引: 指的是List集合中每个元素都是由索引的, 且索引是从0开始的.
- 集合中只能存储相同类型的元素;只有正向索引,没有负向索引。
相关的方法:
sql
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
sql
1.ArrayList集合的特点: 底层数据结构是数组, 查询和修改快, 增删慢.
2.LinkedList集合的特点: 底层数据结构是链表, 查询和修改慢, 增删快.
注意: 它们的相同点是, 都是有序的, 而且可以存储重复元素.
基础的collection相关API使用
java
package com.itheima.list单列集合;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test01_ArrayList集合 {
public static void main(String[] args) {
// 1. 创建ArrayList集合对象
// list: 有序的(添加顺序和存储顺序存在关系) 可重复
List<Integer> list = new ArrayList<>();
//2. 执行相关的操作:
// 2.1 添加数据
list.add(10);
list.add(20);
list.add(25);
list.add(30);
list.add(20);
// 2.2 在指定位置添加数据
list.add(2,100);
// 2.3 将指定的位置的元素进行修改
list.set(2,150);
System.out.println(list);
// 2.4 如何获取元素
Integer e1 = list.get(0);
System.out.println(e1);
Integer e2 = list.get(3);
System.out.println(e2);
// 2.5 获取集合的长度
int size = list.size();
System.out.println(size);
// 2.6 遍历元素
System.out.println("--------------");
// 普通for循环
for(int i = 0 ; i< list.size(); i++){
System.out.println(list.get(i));
}
System.out.println("--------------");
// 普通while循环
int i = 0 ;
while(i< list.size()){
System.out.println(list.get(i));
i++;
}
System.out.println("--------------");
// 增强for循环
for (Integer e : list) {
System.out.println(e);
}
System.out.println("--------------");
// 基于迭代器进行
Iterator<Integer> iterator = list.iterator();
/*
Boolean hasNext() : 判断是否还有下一个元素, 如果有 返回True 如果没有返回False
T next(); 获取下一个元素, 返回的就是下一个元素的值
*/
while (iterator.hasNext()){
Integer e = iterator.next();
System.out.println(e);
}
// 2.7 判断某个元素是否存在
boolean flag = list.contains(1500);
System.out.println(flag);
// 2.8 删除元素
flag = list.remove((Object)150);
System.out.println(flag);
Integer e = list.remove(2);
System.out.println("删除的元素为:"+ e);
// 2.9 清空集合
// 2.9.1 判断 集合是否为空
System.out.println(list.isEmpty());
// 2.9.2 执行清空
list.clear();
// 2.9.3 再次判断集合是否为空
System.out.println(list.isEmpty());
System.out.println(list);
}
}
java
package com.itheima.day04;
import java.util.ArrayList;
public class List列表集合 {
public static void main(String[] args) {
// 创建List,泛型只能使用引用数据类型,不能使用任何的基本数据类型
ArrayList<Integer> list1 = new ArrayList<Integer>();
// 新增
list1.add(11);
list1.add(33);
list1.add(22);
System.out.println(list1);
// 查看
System.out.println(list1.isEmpty());
System.out.println(list1.contains(22));
System.out.println(list1.contains(99));
System.out.println(list1.size());
System.out.println("-----------------------");
// 迭代
for (Integer tmp : list1) {
System.out.println(tmp);
}
list1.forEach(tmp -> System.out.println(tmp));
for (int i = 0; i < list1.size(); i++) {
System.out.println(list1.get(i));
}
System.out.println("-----------------------");
// 删除
// int removeValue = list1.remove(1);
boolean removeValue = list1.remove(Integer.valueOf(11));
System.out.println(removeValue);
list1.clear();
System.out.println(list1);
}
}
需求:
- 定义一个学生类, 属性为姓名和年龄.
- 创建List集合(linkedList), 用来存储学生对象.
- 往List集合中, 添加3个学生的信息. (演示队列的特性)
- 遍历List集合.
java
package com.itheima.list单列集合;
import java.util.Comparator;
import java.util.LinkedList;
public class Test02_LinkedList {
public static void main(String[] args) {
//1. 创建 LinkedList 对象
LinkedList<Student> linkedList = new LinkedList<>();
//2. 执行操作: 主要演示 与队列相关的操作
// 2.1 添加数据: 单端队列
linkedList.offer(new Student("张三",20,"北京"));
linkedList.offer(new Student("李四",18,"上海"));
linkedList.offer(new Student("王五",25,"广州"));
// 2.2 取出元素
// Student s1 = linkedList.poll();
// Student s2 = linkedList.poll();
// Student s3 = linkedList.poll();
// System.out.println(s1);
// System.out.println(s2);
// System.out.println(s3);
// 2.3 对列表中数据进行排序: 要求 按照 对象中 age进行排序
linkedList.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.getAge().compareTo(o1.getAge());
}
});
System.out.println(linkedList);
}
}
java
package com.itheima.day04.list列表案例;
import java.util.Comparator;
import java.util.LinkedList;
public class ListTest {
public static void main(String[] args) {
LinkedList<Student> stuList = new LinkedList<>();
// 从尾部添加元素
stuList.offer(new Student("b",20));
stuList.offer(new Student("a",18));
stuList.offer(new Student("c",23));
System.out.println(stuList);
// 排序
stuList.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// 按年龄降序
// return o2.getAge() - o1.getAge();
// 按年龄升序
return o1.getAge() - o2.getAge();
}
});
// lambda表达式的形式
stuList.sort((o1,o2) -> o2.getAge() - o1.getAge());
System.out.println(stuList);
// 从头部取出元素
System.out.println(stuList.poll());
System.out.println(stuList);
}
}
1.2 常见的数据结构(了解)
数据结构是计算机存储, 组织数据的方式. 它是指相互之间存在一种或多种特定关系的数据元素的集合. 通常情况下, 精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关.
大白话理解:
数据结构指的就是数据的组织方式.
sql
线性数据结构: 线性结构是一个有序数据元素的集合
常用的线性数据结构:
1- 栈
2- 队列
3- 数组
4- 链表
- 栈: 先进后出

- 队列: 先进先出

- 数组: 连续的内存空间
sql
在添加和保存数据的时候, 只能在指定位置下添加数据, 添加和删除的数据效率低一些, 但是其具备高效随机读写的能力
特点:
插入和删除效率低
连续内存,大小固定,无法动态扩展
可以根据下标随机访问,查找效率高
弊端:
增删慢
需要有一块连续内存空间, 对内存使用率不高
- 链表: 不是连续的内存空间, 无固定大小
sql
好处:
对内存使用更加合理, 节省空间
增删快
无固定大小, 可以扩展
弊端:
随机查询的效率低, 因为链接必须从头一步一步检索, 只有知道上一个位置, 才能知道下一个位置

1.3 Set集合
Set集合是Collection集合的子体系, 它的元素特点是无序, 唯一.
注意:
- Set集合是一个接口, 所以不能通过new的方式直接创建它的对象.
- Set集合中没有带索引的方法, 所以不能通过普通for循环遍历.
- Set集合的常用子类主要是HashSet集合
- 只允许存放相同类型的元素
HashSet集合:
sql
1.底层数据结构是哈希表.
2.对集合的迭代顺序不做任何保证, 也就是说不保证元素的存取顺序一致.
3.没有带索引的方法, 所以不能通过普通for循环遍历.
4.由于是Set集合, 所以是不包含重复元素的集合.
总结:
HashSet集合的特点是: 无序, 唯一, 元素无索引, 它的底层数据结构是: 哈希表.
扩展: 所谓的哈希值指的是JDK根据对象的地址, 或者字符串, 或者数字 算出来的int类型的数值.
需求1:
-
1 定义HashSet集合, 存储字符串"hello", "world", "java", "world"
-
2 遍历HashSet集合, 打印每一个元素值, 并观察程序的运行结果.
java
package com.itheima.set单列集合;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Test01_set {
public static void main(String[] args) {
//1. 创建Set集合对象: 无序 去重
Set<String> set = new HashSet<>();
//2. 执行相关的操作:
// 2.1 添加元素
set.add("hello");
set.add("world");
set.add("Hadoop");
set.add("spark");
set.add("Hadoop");
set.add("world");
System.out.println(set);
// 2.2 获取元素的长度
int size = set.size();
System.out.println(size);
// 2.3 判断某个元素是否在set集合中
boolean flag = set.contains("spark");
System.out.println(flag);
// 2.4 遍历set集合:
System.out.println("--------------");
// 增强for循环
for (String e : set) {
System.out.println(e);
}
System.out.println("--------------");
// 迭代器处理
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
需求2:
-
1 定义学生类, 属性为姓名和年龄.
-
2 创建HashSet集合, 用来存储学生对象, 并往其中添加3个学生的信息.
-
3 遍历集合, 并把结果打印到控制台上.
java
package com.itheima.collection;
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 String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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);
}
// 在 set集合中, 如果放置的是对象 要想判断对象是否一致, 底层会调用 hashCode 方法, 基于这个方法判断 是否一致
// 此方法默认返回当前这个地址值的hash值, 重写后 要求其返回数据的hash值
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
package com.itheima.collection;
import java.util.HashSet;
import java.util.Iterator;
public class Demo04_HashSetStudent {
public static void main(String[] args) {
//1. 创建 HashSet集合
HashSet<Student> set = new HashSet<>(); // 去重 无序
//2. 添加元素
set.add(new Student("张三",20));
set.add(new Student("李四",22));
set.add(new Student("王五",25));
set.add(new Student("李四",22));
//3. 遍历打印
for (Student student : set) {
System.out.println(student);
}
}
}
注意: 如果hashset中放置的是对象, 判断数据是否相同的时候, 需要在对象中重写 equals 和 hashCode
1.4 哈希表
-
JDK8以前, 底层采用数组 + 链表的形式实现, 可以理解为: 一个元素为链表的数组.
-
JDK8以后, 在长度比较长的时候, 底层实现了优化.
图解

解释:
1."hello"的哈希值是99162322
2."world"的哈希值是113318802
3."java"的哈希值是3254818
4."world"的哈希值是113318802
5."通话"的哈希值是1179395
6."重地"的哈希值是1179395
7.存储的时候, 会将上述的哈希值和16进行取余操作, 然后根据余数值进行存储. 在每个槽下, 都是基于链表的方式来存储的
2、双列集合
Map集合是双列集合的顶层接口, 它是用来存储键值对对象的 , 其中键具有唯一性 , 而值是可以重复的 . 类似于Python中字典
即: Map集合的数据结构只针对于键有效.
sql
public interface Map<K, V> //K: 键的类型, V: 值的类型.
例如:
•itheima001 刘亦菲
•itheima002 赵丽颖
•itheima003 高圆圆
因为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() | 获取所有值的集合 |
示例: 普通数据
sql
package com.itheima.day04;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Map测试 {
public static void main(String[] args) {
HashMap<String, String> map1 = new HashMap<>();
map1.put("1001","张三");
map1.put("1003","李四");
map1.put("1002","王五");
System.out.println(map1);
System.out.println(map1.containsKey("1001"));
System.out.println(map1.containsKey("1009"));
System.out.println(map1.containsValue("李四"));
System.out.println(map1.containsValue("hello"));
System.out.println(map1.isEmpty());
System.out.println(map1.size());
System.out.println(map1.get("1001"));
System.out.println(map1.get("1009")); // 如果对应的key不存在,返回null
System.out.println(map1.remove("1001"));
System.out.println(map1.remove("1003", "李四11111"));
System.out.println(map1);
System.out.println(map1.remove("1003", "李四"));
HashMap<String, String> map2 = new HashMap<>();
map2.put("1001","张三");
map2.put("1003","李四");
map2.put("1002","王五");
Set<String> keys = map2.keySet();
System.out.println(keys);
Collection<String> values = map2.values();
System.out.println(values);
// map的遍历
map2.forEach((key,value) -> System.out.println(key+value));
Set<Map.Entry<String, String>> entries = map2.entrySet();
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
示例2: 放置对象
java
package com.itheima.map;
import java.util.Objects;
public class Teacher {
public Teacher() {
}
public Teacher(String name, Integer age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
private String name;
private Integer age;
private String address;
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;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", age=" + age +
", address='" + address + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Teacher teacher = (Teacher) o;
return Objects.equals(name, teacher.name) &&
Objects.equals(age, teacher.age) &&
Objects.equals(address, teacher.address);
}
@Override
public int hashCode() {
return Objects.hash(name, age, address);
}
}
package com.itheima.map;
import java.util.HashMap;
public class Demo06_HashMap {
public static void main(String[] args) {
//1. 创建HashMap对象
HashMap<String, Teacher> map = new HashMap<>();
// 2.执行相关操作
map.put("001",new Teacher("LAO WANG",28,"广州"));
map.put("001",new Teacher("LAO ZHANG",28,"上海"));
map.put("001",new Teacher("LAO LI",28,"深圳"));
System.out.println(map);
// 将 对象 作为key
HashMap<Teacher, String> map1 = new HashMap<>();
map1.put(new Teacher("LAO WANG",28,"广州"),"001");
map1.put(new Teacher("LAO WANG",28,"广州"),"002");
map1.put(new Teacher("LAO WANG",28,"广州"),"003");
System.out.println(map1);
}
}
3、Collections集合工具类
Collections类是针对集合操作的工具类.
- 常用方法
方法名 | 说明 |
---|---|
public static void sort(List list) | 将指定的列表按升序排序 |
public static void reverse(List<?> list) | 反转指定列表中元素的顺序 |
public static void shuffle(List<?> list) | 使用默认的随机源随机排列指定的列表 |
示例: 演示相关方法
java
package com.itheima.集合工具类;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Test01_collections {
public static void main(String[] args) {
// 1. 创建一个集合:
ArrayList<String> list = new ArrayList<>();
//2. 添加数据
list.add("hadoop");
list.add("hive");
list.add("spark");
list.add("oozie");
list.add("flink");
list.add("java");
list.add("zookeeper");
list.add("datax");
System.out.println(list);
//3. 执行一些相关的操作:
// 3.1 执行随机打散操作
Collections.shuffle(list);
System.out.println(list);
// 3.2 执行反转操作
Collections.reverse(list);
System.out.println(list);
// 3.3 执行 排序操作
Collections.sort(list);
System.out.println(list);
// Collections.reverse(list);
// System.out.println(list);
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
});
System.out.println(list);
}
}
对象比较处理:
sql
package com.itheima.集合工具类;
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 String toString() {
return "Student{" +
"name='" + name + '\'' +
", 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);
}
// 在 set集合中, 如果放置的是对象 要想判断对象是否一致, 底层会调用 hashCode 方法, 基于这个方法判断 是否一致
// 此方法默认返回当前这个地址值的hash值, 重写后 要求其返回数据的hash值
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
package com.itheima.集合工具类;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Demo08_collections {
public static void main(String[] args) {
//1. 构建一个集合: 类型为对象
ArrayList<Student> list1 = new ArrayList<>();
list1.add(new Student("张三",20));
list1.add(new Student("张三",28));
list1.add(new Student("张三",26));
list1.add(new Student("张三",29));
list1.add(new Student("张三",32));
// 2. 执行操作
// 对 数据进行排序, 要求age排序
Collections.sort(list1, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
System.out.println(list1);
// 取年龄最大值
Student student = Collections.max(list1, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
System.out.println(student);
// 取年龄最大值
student = Collections.min(list1, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
System.out.println(student);
}
}
四、(掌握)Lambda表达式
Lambda表达式本身就是匿名方法(代码块),就是将方法(代码块)赋值给一个变量,lambda的类型都是一个接口。
如何出现的呢?以下演化过程
-
阶段一: Java变量赋值
-
阶段二: 将一个方法或者(代码块)赋值给变量

- 阶段三: 在 java8之后利用 lambda 特性,就可以做到

- 阶段四: 更优雅和简洁的实现
将方法(代码块)赋值给了一个变量,就是一个 lambda 表达式。
1、体验Lambda表达式
需求:
-
1- 已知接口Animal中有一个抽象方法eat()
-
2- 在测试类AnimalTest中定义show(Animal an)方法, 实现调用Animal#eat()方法.
-
3- 并在main方法中, 调用AnimalTest#show()方法.
java
package com.itheima.lambda;
public class Demo10_lambda表达式初体验 {
public static void main(String[] args) {
//1. 创建Animal的对象
Animal cat = new Animal() {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
};
// 调用 方法
execute(cat);
// ==========================================
// 采用 lambda 表达式的方案
Animal animal = () -> System.out.println("狗爱吃骨头");
execute(animal);
}
public static void execute(Animal animal){
animal.eat();
}
}
java
package com.itheima.day04.lambda表达式;
public class Lambda表达式 {
public static void main(String[] args) {
// 匿名内部类
Animal animal = new Animal(){
@Override
public void eat(String food) {
System.out.println("动物吃"+food);
}
};
animal.eat("肠粉");
/*
格式一:
如果形参个数>=2,必须要有小括号
如果代码的行数>=2,必须要有大括号
格式二:
形参的数据类型全部都可以省略
如果代码的行数只有一行,可以省略大括号
格式三:
如果形参有且只有一个,那么可以省略形参外面的小括号
*/
// Lambda表达式:格式一
Animal animal1 = (String food) -> {
System.out.println("动物吃"+food);
};
animal1.eat("辣条");
// Lambda表达式:格式二
Animal animal2 = (food) -> System.out.println("动物吃"+food);
animal2.eat("辣条2");
// Lambda表达式:格式三
Animal animal3 = food -> System.out.println("动物吃"+food);
animal3.eat("辣条3");
}
}
2、Lambda表达式的标准格式
格式:
sql
(形式参数) -> {代码块}
• 形式参数:如果有多个参数,参数之间用逗号隔开, 如果没有参数,留空即可
• ->:由英文中画线和大于符号组成,固定写法。代表指向动作
• 代码块:是我们具体要做的事情,也就是以前我们写的方法体内容
• 组成Lambda表达式的三要素:形式参数,箭头,代码块
Lambda使用的前提条件: 有一个接口, 且接口中有且仅有一个抽象方法.
案例一: 无参无返回值抽象方法
sql
定义一个接口(Eatable),里面定义一个抽象方法:void eat();
定义一个测试类(EatableDemo),在测试类中提供两个方法
一个方法是:useEatable(Eatable e)
一个方法是主方法,在主方法中调用useEatable方法
代码实现:
java
package com.itheima.lambda;
public class Test02_eatable {
public static void main(String[] args) {
// 匿名内部类
// Eatable e = new Eatable() {
// @Override
// public void eat() {
// System.out.println("吃东西...");
// }
// };
// lambda表达式写法: 相当于重写 接口 eat 方法
Eatable e = () -> {
System.out.println("吃东西...");
};
useEatable(e);
}
public static void useEatable(Eatable e){
e.eat();
}
}
案例二: 有参无返回值抽象方法的练习
sql
定义一个接口(Flyable),里面定义一个抽象方法:void fly(String s);
定义一个测试类(FlyableDemo),在测试类中提供两个方法
一个方法是:useFlyable(Flyable f)
一个方法是主方法,在主方法中调用useFlyable方法
代码实现:
java
package com.itheima.lambda;
public class Test03_Flyable {
public static void main(String[] args) {
// Flyable f = (String s) -> {
// System.out.println(s +"要飞");
// };
// 省略写法:
// 省略1: 当 {} 中代码块只有一行的时候, 可以省略 {} 以及 分号
// Flyable f = (String s) -> System.out.println(s +"要飞");
// 省略2: () 里面的参数类型 可以不写, 如果有多个参数, 要省略一起省略
//Flyable f = (s) -> System.out.println(s +"要飞");
// 省略3: () 里面只有一个参数, 可以省略 小括号
//Flyable f = s -> System.out.println(s +"要飞");
//useFlyable(f);
// 合并在一起:
useFlyable(s -> System.out.println(s +"要飞"));
}
public static void useFlyable(Flyable f){
f.fly("老张");
}
}
案例三: 有参有返回值抽象方法的练习
sql
定义一个接口(Addable),里面定义一个抽象方法:int add(int x,int y);
定义一个测试类(AddableDemo),在测试类中提供两个方法
一个方法是:useAddable(Addable a)
一个方法是主方法,在主方法中调用useAddable方法
java
package com.itheima.lambda;
public class Test04_Addable {
public static void main(String[] args) {
// Addable a = (int x,int y) -> {
// return x + y;
// };
// 省略操作:
Addable a = (x,y) -> x + y;
useAddable(a);
}
public static void useAddable(Addable a){
int sum = a.add(3, 5);
System.out.println(sum);
}
}
案例四: 模拟一下 Spark中 map方法: 传入一个 返回一个操作
java
package com.itheima.lambda;
public interface SparkRDD<IN,OUT> {
public OUT map(IN data);
}
package com.itheima.lambda;
import java.util.Arrays;
import java.util.List;
public class Demo14_SparkRDDTest {
public static void main(String[] args) {
List<String> list = map(data -> Arrays.asList(data.split(" "))); // 仅仅是在定义处理数据的逻辑
System.out.println(list);
}
public static List<String> map(SparkRDD<String,List<String>> rdd){
return rdd.map("hello world spark hadoop");
}
}
3、Lambda省略模式
规则:
- 参数类型可以省略。但是有多个参数的情况下,不能只省略一个
- 如果参数有且仅有一个,那么小括号可以省略
- 如果代码块的语句只有一条,可以省略大括号和分号,和return关键字
4、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: 结果集或一张虚拟表
1、JDBC原理
Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。

**JDBC的核心作用是为了实现代码程序与具体数据库产品解耦。**JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。
2、JDBC入门案例
-
1- 在Java的项目中, 创建一个 lib的目录
-
2- 将资料中提供的Mysql驱动jar包, 添加到lib目录下
-
3- 让整个项目加载到当前这个依赖驱动jar包

2.1 查询表中数据
准备工作: 打开MySQL, 创建表, 添加一些测试数据
sql
create database day04_jdbc char set 'utf8';
use day04_jdbc;
create table stu(
id int primary key,
name varchar(20),
age int,
address varchar(20)
);
insert into stu (id,name,age,address) values(1,'张三',20,'北京');
insert into stu (id,name,age,address) values(2,'李四',18,'上海');
insert into stu (id,name,age,address) values(3,'王五',22,'广州');
insert into stu (id,name,age,address) values(4,'赵六',28,'深圳');
insert into stu (id,name,age,address) values(5,'田七',23,'杭州');
代码编写:
sql
JDBC使用六大步:
1- 注册驱动 : Class.forName("com.mysql.jdbc.Driver");
2- 获取连接对象 :Connection conn = DriverManager.getConnection(url,username,password)
3- 根据连接对象, 创建语句执行平台
方式一: Statement stat1 = conn.createStatement()
方式二: Statement stat2 = conn.prepareStatement(String sql)
4- 执行SQL
针对方式一的执行平台:
Boolean flag = stat1.execute(SQL): 执行 增 删 改 返回false, 如果执行查询返回true
int i = stat1.executeUpdate(SQL): 返回值表示影响了多少行
ResultSet rs = stat1.executeQuery(SQL): 表示返回的结果集对象, 此对象为二维的表
Boolean flag = rs.next(); 指向下一行数据, 如果没有 返回false
Xxx 变量 = rs.getXxx('字段'); 获取指定列的数据, Xxx表示此列的数据类型
针对方式二的执行平台:
stat2.setXxx(int I, Xxx data); 为SQL中对应参数赋值 (后面讲的时候说)
Boolean flag = stat2.execute(): 执行 增 删 改 返回false, 如果执行查询返回true
int i = stat2.executeUpdate(): 返回值表示影响了多少行
ResultSet rs = stat2.executeQuery(): 表示返回的结果集对象, 此对象为二维的表
Boolean flag = rs.next(); 指向下一行数据, 如果没有 返回false
Xxx 变量 = rs.getXxx('字段'); 获取指定列的数据, Xxx表示此列的数据类型
5- 处理结果集:
增 删 改不需要处理, 简单打印一下返回的受影响行即可
查询: 对ResultSet结果集 进行遍历获取每一行, 每一列的数据
6- 释放资源:
所有涉及到对象, 只有有close的方法, 都需要关闭, 关闭资源遵循从后往前关闭
代码实现:
java
package com.itheima.day04;
import java.sql.*;
public class JDBC操作案例 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1- 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2- 获取数据库连接
String url = "jdbc:mysql://192.168.88.166:3306/day04_jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false";
Connection conn = DriverManager.getConnection(url, "root", "123456");
// 3- 获取执行SQL语句的对象
Statement statement = conn.createStatement();
// 4- 执行SQL
String sql = "select * from stu";
ResultSet rs = statement.executeQuery(sql);
System.out.println(rs);
// 5- 处理返回结果
while (rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
String address = rs.getString("address");
System.out.println(id+","+name+","+age+","+address);
}
// 6- 释放资源
rs.close();
statement.close();
conn.close();
}
}
2.2 如何添加数据
java
package com.itheima.day04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC操作案例新增 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1- 注册驱动。通过反射创建
Class.forName("com.mysql.jdbc.Driver");
// 2- 获取数据库连接
String url = "jdbc:mysql://192.168.88.166:3306/day04_jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false";
Connection conn = DriverManager.getConnection(url, "root", "123456");
// 3- 获取SQL执行对象
Statement statement = conn.createStatement();
// 4- 执行插入语句
String sql = "insert into stu (id,name,age,address) values(6,'王六',22,'深圳')";
// 表示影响的数据条数
int result = statement.executeUpdate(sql);
System.out.println(result);
// 5- 释放资源
statement.close();
conn.close();
}
}
2.3 如何修改数据
java
package com.itheima.day04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC操作案例更新 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1- 注册驱动。通过反射创建
Class.forName("com.mysql.jdbc.Driver");
// 2- 获取数据库连接
String url = "jdbc:mysql://192.168.88.166:3306/day04_jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false";
Connection conn = DriverManager.getConnection(url, "root", "123456");
// 3- 获取SQL执行对象
Statement statement = conn.createStatement();
// 4- 执行更新语句
String sql = "update stu set name='周六',age=99 where id=6";
// 表示影响的数据条数
int result = statement.executeUpdate(sql);
System.out.println(result);
// 5- 释放资源
statement.close();
conn.close();
}
}
2.4 如何删除数据
java
package com.itheima.day04;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBC操作案例删除 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1- 注册驱动。通过反射创建
Class.forName("com.mysql.jdbc.Driver");
// 2- 获取数据库连接
String url = "jdbc:mysql://192.168.88.166:3306/day04_jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false";
Connection conn = DriverManager.getConnection(url, "root", "123456");
// 3- 获取SQL执行对象
Statement statement = conn.createStatement();
// 4- 执行删除语句
String sql = "delete from stu where id=6";
// 表示影响的数据条数
int result = statement.executeUpdate(sql);
System.out.println(result);
// 5- 释放资源
statement.close();
conn.close();
}
}
说明:
sql
1- 完成 每个集合的常用API的使用, 建议可以通过查看API帮助文档来操作
2- 完成Lambda表达式的案例演示: 有参数 无参 有返回值 五返回值 (尝试使用省略的方式来写)
3- 完成JDBC的操作的CURD
4- 将之前的登录案例, 尝试连接数据库实现: 在数据库中创建一个表, 有用户名 和 密码. 让用户输入 , 输入后和系统的用户名和密码进行比对, 如果成功, 返回登录成功, 否则登录失败