当前位置: 首页 > article >正文

day04_Java高级

文章目录

  • day04_Java高级
    • 一、今日课程内容
    • 二、可变参数
    • 三、Java的集合
      • 1、单列集合
        • 1.1 List集合
        • 1.2 常见的数据结构(了解)
        • 1.3 Set集合
        • 1.4 哈希表
      • 2、双列集合
      • 3、Collections集合工具类
    • 四、(掌握)Lambda表达式
      • 1、体验Lambda表达式
      • 2、Lambda表达式的标准格式
      • 3、Lambda省略模式
      • 4、Lambda表达式和匿名内部类的区别
    • 五、JDBC协议
      • 1、JDBC原理
      • 2、JDBC入门案例
        • 2.1 查询表中数据
        • 2.2 如何添加数据
        • 2.3 如何修改数据
        • 2.4 如何删除数据

day04_Java高级

一、今日课程内容

  • 可变参数(熟悉)
  • Java的集合(掌握)
  • lambda表达式(掌握)
  • JDBC的协议(熟悉,JavaEE的框架)

二、可变参数

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

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

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

格式:

修饰符 返回值类型 方法名(形参1,形参2,数据类型… 变量名) {  }


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

需求:

  • 1- 定义getSum()方法, 用来获取n个整数的和(n可能是任意的一个数字).
  • 2- 在main方法中, 调用getSum()方法.
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

集合体系图:

记忆
集合的顶层都是接口, 其中Collection接口是单列集合的顶层接口, Map接口是双列集合的顶层接口

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

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

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

1、单列集合

​ 集合是用来存储多个同类型数据的容器, 它的长度是可以变化的.

collection常用方法如下:

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集合的元素特点是: 有序, 可重复, 元素有索引.

  1. 有序: 指的是元素的存储顺序和取出顺序是一致的.
  2. 可重复: 指的是List集合可以存储重复的元素.
  3. 元素有索引: 指的是List集合中每个元素都是由索引的, 且索引是从0开始的.
  4. 集合中只能存储相同类型的元素;只有正向索引,没有负向索引。

相关的方法:

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.ArrayList集合的特点: 底层数据结构是数组, 查询和修改快, 增删慢.
2.LinkedList集合的特点: 底层数据结构是链表, 查询和修改慢, 增删快. 

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

基础的collection相关API使用

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);

    }
}

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集合.
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);

    }

}
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 常见的数据结构(了解)

​ 数据结构是计算机存储, 组织数据的方式. 它是指相互之间存在一种或多种特定关系的数据元素的集合. 通常情况下, 精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关.

大白话理解:

数据结构指的就是数据的组织方式.
线性数据结构: 线性结构是一个有序数据元素的集合
常用的线性数据结构:
1-2- 队列
3- 数组 
4- 链表
  • 栈: 先进后出

在这里插入图片描述

  • 队列: 先进先出

在这里插入图片描述

  • 数组: 连续的内存空间
	在添加和保存数据的时候, 只能在指定位置下添加数据, 添加和删除的数据效率低一些, 但是其具备高效随机读写的能力

特点:	
	插入和删除效率低
	连续内存,大小固定,无法动态扩展
	可以根据下标随机访问,查找效率高

弊端: 
	增删慢
	需要有一块连续内存空间, 对内存使用率不高
  • 链表: 不是连续的内存空间, 无固定大小
好处: 
	对内存使用更加合理, 节省空间
	增删快
	无固定大小, 可以扩展
弊端: 
	随机查询的效率低, 因为链接必须从头一步一步检索, 只有知道上一个位置, 才能知道下一个位置

在这里插入图片描述

1.3 Set集合

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

注意:

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

HashSet集合:

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

总结: 
HashSet集合的特点是: 无序, 唯一, 元素无索引, 它的底层数据结构是: 哈希表. 
 
扩展: 所谓的哈希值指的是JDK根据对象的地址, 或者字符串, 或者数字 算出来的int类型的数值. 

需求1:

  • 1 定义HashSet集合, 存储字符串"hello", “world”, “java”, “world”

  • 2 遍历HashSet集合, 打印每一个元素值, 并观察程序的运行结果.

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 遍历集合, 并把结果打印到控制台上.

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集合的数据结构只针对于有效.

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()获取所有值的集合

示例: 普通数据

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: 放置对象

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)使用默认的随机源随机排列指定的列表

示例: 演示相关方法

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);
    }

}

对象比较处理:

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()方法.

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();
    }

}

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表达式的标准格式

格式:

(形式参数) -> {代码块}

• 形式参数:如果有多个参数,参数之间用逗号隔开, 如果没有参数,留空即可

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

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

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

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

案例一: 无参无返回值抽象方法

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

代码实现:

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();
    }

}

案例二: 有参无返回值抽象方法的练习

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

代码实现:

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("老张");
    }

}


案例三: 有参有返回值抽象方法的练习

定义一个接口(Addable),里面定义一个抽象方法:int add(int x,int y);
定义一个测试类(AddableDemo),在测试类中提供两个方法
	一个方法是:useAddable(Addable a)
	一个方法是主方法,在主方法中调用useAddable方法
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方法: 传入一个 返回一个操作

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, 创建表, 添加一些测试数据

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,'杭州');

代码编写:

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的方法, 都需要关闭, 关闭资源遵循从后往前关闭

代码实现:

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 如何添加数据
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 如何修改数据
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 如何删除数据
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();
    }
}

说明:

1- 完成 每个集合的常用API的使用, 建议可以通过查看API帮助文档来操作

2- 完成Lambda表达式的案例演示:  有参数 无参 有返回值 五返回值 (尝试使用省略的方式来写)

3- 完成JDBC的操作的CURD 

4- 将之前的登录案例, 尝试连接数据库实现: 在数据库中创建一个表, 有用户名 和 密码. 让用户输入 , 输入后和系统的用户名和密码进行比对, 如果成功, 返回登录成功, 否则登录失败

http://www.kler.cn/a/587978.html

相关文章:

  • 练习题:89
  • 考研专业课复习方法:如何高效记忆和理解?
  • 应用于电池模块的 Fluent 共轭传热耦合
  • C++学习笔记(二十)——类之运算符重载
  • 代码随想录算法训练营第32天 | 509. 斐波那契数 70. 爬楼梯 746. 使用最小花费爬楼梯
  • 【数据分析】读取文档(读取Excel)
  • Varjo:为战场各兵种综合训练提供XR技术支持
  • DeepSeek-R1大模型微调技术深度解析:架构、方法与应用全解析
  • 【论文阅读】Cross-View Fusion for Multi-View Clustering
  • Flash Attention原理讲解
  • 【Linux】:socket编程——UDP
  • 传输层tcp/udp
  • 287. 寻找重复数
  • Python实现万年历
  • DAY34 贪心算法Ⅲ
  • C++模版(复习)
  • C++|类和对象
  • Android 拍照开发——移动虚拟机摄像头
  • java简单基础学习
  • 关于离子滤波小记