JDK1.8新特性

 

目录

 

一、Lambda表达式

        1.1 匿名内部类的冗余

        1.2 自定义无参无返回值的函数式接口

         1.3 自定义有参有返回值的函数式接口

        二、函数式接口

        2.1 Consumer 消费性函数式接口

        2.2 Supplier 供给型函数式接口

        3.3 Funcation 函数型函数式接口,r>

         3.4 Predicate 断言型函数式接口

        四、方法引用的使用场景

        4.1 方法引用的分类

        4.2 方法引用的举例

        五、Stream流

        5.1 为什么要用Stream流

        5.2 Stream流式思想概述

        5.2.1 获取Stream流对象

        5.2.2   中间操作的方法有哪些

        六、讲解Stream流

        6.1 Stream中的API

        6.1.1  filter 筛选操作

        6.1.2 map 映射操作

        6.1.3 sort排序操作

        6.1.4 提取和组合

        6.1.5 find操作--findFirst和findAny  

        6.1.6 match 匹配操作--allMatch anyMatch

        6.1.7  聚合操作 max min count

        6.1.8 reduce规约操作

        6.2 collect搜集操作

        七、JDK8中日期时间类

        7.1 日期时间

        7.2 把日期时间转化为字符串和字符串解析为日期时间

        7.3 日期时间比较类.


一、Lambda表达式

        概念:Lambda表达式:特殊的匿名内部类,语法更简洁

                   Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递

         匿名内部类:无需创建接口的实现类,可以之间创建接口对象

   Runnable runnable=new Runnable() {
         @Override
         public void run() {

         }
    };

         调用方法时:传递的参数可以是 基本类型,引用类型

        语法:

        函数式接口: 接口有只有一个抽象方法。这种接口就是函数式接口。

        我们要想使用lambda表示,它的接口必须为函数式接口。

        箭头左边:抽象方法的参数

        ->: 运算符

        箭头右边: 抽象方法的方法体。

        

        1.1 匿名内部类的冗余

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


        //构造函数需要传递一个Runnable target类型的参数。而Runnable它是一个接口。
        MyRunnable my=new MyRunnable();
        Thread t=new Thread(my);
        t.start();


        //使用匿名内部类
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                System.out.println("~~~~~~~~~~~~~~这是匿名内部类");
            }
        };
        Thread t2=new Thread(runnable);
        t2.start();



    }
}
class MyRunnable implements Runnable{

    @Override
    public void run() {
        System.out.println("~~~~~~~~~~~~~~这是自定义接口实现类");
    }
}

分析代码:

  • Thread 类需要 Runnable 接口作为参数,其中的抽象 run 方法是用来指定线程任务内容的核心

  • 为了指定 run 的方法体,不得不需要 Runnable 接口的实现类

  • 为了省去定义一个 Runnable 实现类的麻烦,不得不使用匿名内部类

  • 必须覆盖重写抽象 run 方法,所以方法名称、方法参数、方法返回值不得不再写一遍,且不能写错

  • 而实际上,似乎只有方法体才是关键所在。

                        我们就可以使用Lambda表达式  

 //lambda表达式 没有关注方法的名称 以及方法的返回类型 --lambda表示不会生成字节码文件
        Runnable r=()->{
            System.out.println("这是lambda表达式");
        };
        Thread t3=new Thread(r);
        t3.start();

        1.2 自定义无参无返回值的函数式接口

public class Test {
    public static void main(String[] args) {
        Swimming s=new Swimming() {
            @Override
            public void swiming() {
                System.out.println("~~~~~~~~~~~~匿名内部类");
            }
        };
        fun(s);


        Swimming s2=()->{
            System.out.println("lambda表达式============");
        };
        fun(s2);

    }

    //定义一个方法---传递的参数为接口类型---函数式接口
    public static void fun(Swimming s){
          s.swiming();
    }
}
//它就是函数式接口
@FunctionalInterface
interface Swimming{
    public void swiming();
}

         1.3 自定义有参有返回值的函数式接口

public class Test02 {
    public static void main(String[] args) {
        //无需参数类型
        Operator o = (arr) -> {
            int sum = 0;
            for (int b : arr) {
                sum += b;
            }
            return sum;
        };


        fun(o);
    }

    public static void fun(Operator operator) {
        int sum[] = {11, 12, 13, 14};
        int sum1 = operator.getSum(sum);
        System.out.println("数组中元素的和:" + sum1);
    }
}

interface Operator {
    //求数组中元素的和
    public int getSum(int[] arr);
}

 下面举例演示 java.util.Comparator 接口的使用场景代码,其中的抽象方法定义为:

  • public abstract int compare(T o1, T o2);

当需要对一个对象集合进行排序时, Collections.sort 方法需要一个 Comparator 接口实例来指定排序的规则。

public class Test03 {
    public static void main(String[] args) {
        List<Student> list=new ArrayList<>();
        list.add(new Student("柳昌江",16));
        list.add(new Student("汪豪杰",17));
        list.add(new Student("闫克起",15));
        list.add(new Student("刘洺宇",16));
        //List<T> list,要排序的集合
        // Comparator<? super T> c: 指明排序的规则
//        Comparator<Student> comparator=new Comparator<Student>() {
//            //返回0 表示o1和o2 相同 返回大于0
//            @Override
//            public int compare(Student o1, Student o2) {
//                return o1.getAge()-o2.getAge();
//            }
//        };

        Comparator<Student> comparator=(o1,o2)->{return o2.getAge()-o1.getAge();};
        Collections.sort(list,comparator);
        System.out.println(list);
    }
}


class Student{
    private String name;
    private Integer age;

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

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

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

        1.4 详细介绍Lambda表达式

                        什么时候使用lambda表达式?

                        调用某个方法时,该方法需要传递一个函数式接口参数时

        

        二、函数式接口

        概念: 如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。

        @FunctionalInterface 注解检测接口是否符合函数式接口

        内置函数式接口的由来

public class Test {
    public static void main(String[] args) {
        Operator o=arr -> arr.length;
        fun(o);
    }
    public static void fun(Operator operator) {
        int sum[] = {11, 12, 13, 14};
        int sum1 = operator.getSum(sum);
        System.out.println("数组中元素的个数:" + sum1);
    }
}

interface Operator {
    //求数组中元素的和
    public int getSum(int[] arr);
}

 分析

我们知道使用Lambda表达式的前提是需要有函数式接口。而Lambda使用时不关心接口名,抽象方法名,只关心抽 象方法的参数列表和返回值类型。因此为了让我们使用Lambda方便,JDK提供了大量常用的函数式接口。 ---无需自定义函数式接口。---如果JDK不提供一些函数式接口,那么每个人需要自定义函数式接口,而且每个人定义的名称不一致。

                内置的函数式接口都在 java.util.function包下  

         

        2.1 Consumer<T> 消费性函数式接口

        T: 参数的泛型

        void accept(T t);

        方法中有参,无返回值。

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/11/3 12:11
 * @Version 1.0
 */
package com.wjk.demo05;

import java.util.function.Consumer;

/**
 * 消费性函数式接口
 * 有参无返回值
 * 如果需要一个有参返回值的函数式接口,那么我们就可以使用Consumer函数式即可,无需自定义函数式接口
 */
public class Test05 {
    public static void main(String[] args) {
        Consumer<Double> consumer=a -> {
            System.out.println("吃烧烤需要花:"+a);
        };

        fun(consumer,9999.99);
    }

    public static void fun(Consumer<Double> consumer,Double money){
        consumer.accept(money);
    }
}

        2.2 Supplier<T> 供给型函数式接口

        T:表示方法的返回值泛型  T get();

        方法没有参数,有返回值。 当我们需要无参有返回值的函数式接口,就可以使用这种内置

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/11/3 12:15
 * @Version 1.0
 */
package com.wjk.demo06;

import java.util.function.Supplier;

/**
 *  T:表示方法的返回值泛型
 *  方法没有参数,有返回值 当我们需要无参有返回值的函数式接口时,就可以用这种内置
 *  fun是自己写的方法,未来可能调用jdk自带的方法,参数也可能就是上面给的函数式接口。
 */
public class Test06 {
    public static void main(String[] args) {
        Supplier<String> s=()->{
            return "八嘎";
        };
        fun(s);
    }

    public static void fun(Supplier<String> supplier){
        String s = supplier.get();
        System.out.println(s);
    }
}

        3.3 Funcation<T,R> 函数型函数式接口

        T:参数的泛型
        R: 返回值的泛型
        R apply(T t);
        这种函数式接口需要参数和有返回值。

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/11/3 12:18
 * @Version 1.0
 */
package com.wjk.demo07;


import java.util.function.Function;

/**
 *  Funcation<T,R> 函数型函数式接口
 *  T:参数的泛型
 *  R: 返回值的泛型
 *  R apply(T t);
 *  这种函数式接口需要参数和有返回值
 */
public class Test07 {
    public static void main(String[] args) {

        Function<String,Integer> function=t->t.length();

        fun(function,"hahahahahahahhahahahahahahahhaha");
    }
    public static void fun(Function<String,Integer> f,String str){
        Integer apply = f.apply(str);
        System.out.println(apply);
    }
}

         3.4 Predicate<T> 断言型函数式接口

        boolean test(T t);

        泛型: 参数的类型

        返回值: boolean

        根据参数做相应的条件判断,如果满足条件则返回true,不满足则返回false.

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/11/4 9:11
 * @Version 1.0
 */
package com.wjk.demo1104.demo01;

import java.util.function.BiPredicate;
import java.util.function.Predicate;

/**
 * 断言型函数式接口
 */
public class TestPredicate {
    public static void main(String[] args) {

        //根据你传递的字符串,判断字符串的长度是否大于5
        Predicate<String> p=t->{
            return t.length()>5;
        };

        boolean baga = p.test("hello baga");
        System.out.println(baga);

        //boolean test (T t,U u)
        BiPredicate<String,String> biPredicate=(t,u)->{
            return t.equals(u);
        };

        boolean test = biPredicate.test("baga", "guizi");
        System.out.println(test);
    }
}

        四、方法引用的使用场景

        我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用方法外,没有其他任何多余的动作,在这种情况下,我们倾向于通过方法名来调用它,而Lambda表达式可以帮助我们实现这一要求,它使得Lambda在调用那些已经拥有方法名的方法的代码更简洁、更容易理解。方法引用可以理解为Lambda表达式的另外一种表现形式。方法引用要比lambda表达式语法更加简洁

        方法引用: 理解为Lambda表达式的另一种表现。它的语法更加简洁。

        方法引用使用的前提: lambda表达式中调用的是已经存在的方法,除了调用方法外,不能有任何其他操作,才可以使用方法引用。

        4.1 方法引用的分类

类型语法对应的LAMBDA表达式
静态方法引用类名::staticMethod(args) -> 类名.staticMethod(args)
实例方法引用inst::instMethod(args) -> inst.instMethod(args)
对象方法引用类名::instMethod(inst,args) -> inst.instMethod(args)
构建方法引用类名::new(args) -> new 类名(args)

                                ::  是方法引用的符号。  

        4.2 方法引用的举例

              静态方法的引用:当lambda表达式中,通过类名引用了一个已经存在的静态方法时。而且仅有一条语句

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

        //void accept(T t);
        //Consumer<int[]> consumer=(arr)->{Test01.sum(arr);};
        //观察: 我们发现lambda表达式中有且仅有一条一句,而且这条语句,是调用了已经存在的方法。
        Consumer<int[]> consumer=Test01::sum;
        int[] arr={1,2,3,4};
        consumer.accept(arr);
    }

    public static void sum(int[] arr) {
        int sum = 0;
        for (int a : arr) {
            sum += a;
        }
        System.out.println("数组中元素的和:"+sum);

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

        List<Integer> list=new ArrayList<>();
        list.add(2);
        list.add(3);
        list.add(8);
        list.add(4);
        list.add(1);
        //Comparator<Integer> comparator=(o1,o2)->Integer.compare(o1,o2);
        Comparator<Integer> comparator=Integer::compare;
        Collections.sort(list,comparator);

        System.out.println(list);
    }
}

        实例方法的引用:实例方法引用 inst::instMethod (args) -> inst.instMethod(args)

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/11/4 10:16
 * @Version 1.0
 */
package com.wjk.demo1104.demo03;

import java.util.function.Supplier;

/**
 * 实例方法引用
 */
public class Test03 {
    public static void main(String[] args) {
        //无参 有返回值
        Teacher teacher=new Teacher("闫克起","35");

        //Supplier<String> supplier=()-> teacher.getName();

        //方法引用
        Supplier<String> supplier=teacher::getName;
        Supplier<String> supplier1=teacher::getAge;

        System.out.println(supplier.get()+"********"+supplier1.get());



    }
}
class Teacher{
    private String name;
    private String age;

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

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

    public String getName() {
        return name;
    }

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

    public String getAge() {
        return age;
    }

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

        对象方法引用 类名::instMethod (inst,args) -> inst.instMethod(args)

        当lambda表达式第一个参数调用方法,而后面的参数作为方法的参数时。 我们可以考虑使用对象方法引用。 

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/11/4 10:19
 * @Version 1.0
 */
package com.wjk.demo1104.demo04;

import java.util.function.BiPredicate;

/**
 * 对象方法引用
 */
public class Test {
    public static void main(String[] args) {
        //比较两个字符串是否一致  断言式函数式接口
//        BiPredicate<String,String> biPredicate=(o1,o2)->{
//            return o1.equals(o2);
//        };

        //对象方法引用
        BiPredicate<String,String> biPredicate=String::equals;

        boolean test = biPredicate.test("八嘎", "baag");
        System.out.println(test);
    }
}

        构建方法引用 类名::new (args) -> new 类名(args)

        lambda表达式中只有一条语句,而且这条数据是实例一个对象,调用构造方法,而且构造函数的参数和lambda表达式的参数一致。  

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/11/4 10:23
 * @Version 1.0
 */
package com.wjk.demo1104.demo05;

import java.util.function.Function;
import java.util.function.Supplier;

/**
 * 构造方法引用
 */
public class Test {
    public static void main(String[] args) {
        //Function<String,Teacher> function=(t)->new Teacher(t);

        //构造方法引用
        Function<String,Teacher> function=Teacher::new;

        Teacher apply = function.apply("闫克起");
        System.out.println(apply);

    }
}
class Teacher{
    private String name;

    public Teacher() {
    }

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

    public Teacher(String name) {
        this.name = name;
    }

}

        五、Stream流

        Java8的两个重大改变,一个是Lambda表达式,另一个就是本节要讲的Stream API表达式。Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找、过滤、筛选等操作.

        这种操作速度,要比操作数据库更快。 引用它基于JVM内存.

        5.1 为什么要用Stream流

当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。我们来体验 集合操作数据的弊端,需求如下:

        一个ArrayList集合中存储有以下数据:张无忌,周芷若,赵敏,张强,张三丰
        需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据

        代码如下:

public class Test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");

        //1.获取所有姓张。
        ArrayList<String> newList = new ArrayList<>();
        for(String n:list){
              if(n.startsWith("张")){
                  newList.add(n);
              }
        }

        //2. 名字中含有三个的字
        ArrayList<String> newList2 = new ArrayList<>();
        for(String n:newList){
              if(n.length()==3){
                  newList2.add(n);
              }
        }

        //3.打印
        for (String s:newList2){
            System.out.println(s);
        }

    }
}

        不过循环遍历有个弊端 这段代码中含有三个循环,每一个作用不同:

  1. 首先筛选所有姓张的人;

  2. 然后筛选名字有三个字的人;

  3. 最后进行对结果进行打印输出。

每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。这是理所当然的么?不是。循环 是做事情的方式,而不是目的。每个需求都要循环一次,还要搞一个新集合来装数据,如果希望再次遍历,只能再使 用另一个循环从头开始。

                那Stream能给我们带来怎样更加优雅的写法呢?

                使用Stream流来体验上面对集合的操作。

public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");


       // Consumer<String> consumer=item-> System.out.println(item);
        list.stream()
                .filter(item->item.startsWith("张"))
                .filter(item->item.length()==3)
                .forEach(item-> System.out.println(item));

    }

        5.2 Stream流式思想概述

        Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工 处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

        

        5.2.1 获取Stream流对象

        这里获取流对象的方式有三种:    1. 通过集合名获取。 2. 通过Arrays中的静态方法获取streams  3. 通过Stream中的静态方法of

                拿到流对象后才能操作Stream类中相关的方法

public class Test02 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
        //通过集合对象调用stream方法获取
        Stream<String> stream = list.stream();

        //通过Arrays数组工具类调用stream方法。
        String [] arr={"张三","李四","王五"};
        Stream<String> stream1 = Arrays.stream(arr);

        //通过Stream类中的方法获取Stream流对象
        Stream<String> stream2 = Stream.of("张三", "李四", "王五");
    }
}

        5.2.2   中间操作的方法有哪些

        一个操作的中间链,对数据源的数据进行操作。

        举个简单的例子:

        假设有一个Person类和一个Person列表,现在有两个需求:1)找到年龄大于18岁的人并输出;2)找出所有中国人的数量。

/**
 * Created by Intellij IDEA
 *
 * @author 王俊凯
 * @Date: 2022/11/4 14:27
 * @Version 1.0
 */
package com.wjk.demo1104.demo07;

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

public class Test02 {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));
        //找出年龄大于18
        personList.stream().filter(item->{
            return item.getAge()>18;
        }).forEach(System.out::println);

        System.out.println("*****************************");

        //找出所有中国人
        personList.stream().filter(item->item.getCountry().equals("中国")).forEach(System.out::println);
    }
}
class Person {
    private String name;
    private Integer age;
    private String country;
    private char sex;

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

    public Person() {
    }

    public Person(String name, Integer age, String country, char sex) {
        this.name = name;
        this.age = age;
        this.country = country;
        this.sex = sex;
    }

    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 getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
}

        六、讲解Stream流

        6.1 Stream中的API

        中间操作api: 一个操作的中间链,对数据源的数据进行操作。而这种操作的返回类型还是一个Stream对象。---中间操作如果没有调用终止操作的api,则中间操作的api不会被执行。

        终止操作api: 一个终止操作,执行中间操作链,并产生结果,返回类型不在是Stream流对象。

        6.1.1  filter 筛选操作

        该方法需要一个断言型函数式接口参数,满足条件的留下,不满足条件的过滤掉。

public class Test03 {
    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));

        //筛选出年龄大于20
//        personList.stream().filter(item -> item.getAge() > 20).forEach(item-> System.out.println(item));
        
        personList.stream().filter(item -> item.getAge() > 20).forEach(System.out::println);


    }
}
class Person {
    private String name;
    private Integer age;
    private String country;
    private char sex;

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

    public Person() {
    }

    public Person(String name, Integer age, String country, char sex) {
        this.name = name;
        this.age = age;
        this.country = country;
        this.sex = sex;
    }

    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 getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }
}

        6.1.2 map 映射操作

        map--接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

 

 List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));

        //map映射操作--名称
        personList.stream().map(item->item.getName()).forEach(System.out::println);

        6.1.3 sort排序操作

  List<Person> personList = new ArrayList<>();
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));

        //sort排序操作--年龄
        personList.stream().sorted((o1,o2)->Integer.compare(o1.getAge(),o2.getAge())).forEach(System.out::println);

        6.1.4 提取和组合

        流也可以进行合并、去重、限制、跳过等操作。        filter map sort concat distinct limit skip

public class Test04 {
    public static void main(String[] args) {
        String[] arr1 = { "a", "b", "c", "d" };
        String[] arr2 = { "d", "e", "f", "g" };
        Stream<String> stream1 = Stream.of(arr1);
        Stream<String> stream2 = Stream.of(arr2);

        //合并流
        //Stream.concat(stream1,stream2).forEach(System.out::println);
        //去重--distinct
       // Stream.concat(stream1,stream2).distinct().forEach(System.out::println);

        //获取前n个元素--limit
        //Stream.concat(stream1,stream2).limit(5).forEach(System.out::println);

        //跳过前n个元素
        Stream.concat(stream1,stream2).skip(2).forEach(System.out::println);
    }
}

        6.1.5 find操作--findFirst和findAny  

  List<Person> personList = new ArrayList<>();
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));

        //find操作-- findFirst 获取流中第一个元素
//        Optional<Person> first = personList.stream().findFirst();
//        System.out.println(first.get());
        //find操作---findAny() 获取流中任意一个元素  必须使用并行流测试
        Optional<Person> any = personList.parallelStream().findAny();
        System.out.println(any.get());

        6.1.6 match 匹配操作--allMatch anyMatch

 List<Person> personList = new ArrayList<>();
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));

        //匹配操作--所有元素都必须匹配条件 才返回true
//        boolean b = personList.stream().allMatch(item -> item.getAge() > 10);
//        System.out.println(b);
        boolean b = personList.stream().anyMatch(item -> item.getAge() > 50);
        System.out.println(b);

        6.1.7  聚合操作 max min count

   List<Person> personList = new ArrayList<>();
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));

        //聚合操作---count
//        long count = personList.stream().count();
//        System.out.println("个数:"+count);
        //聚合操作---max min
        Optional<Person> max = personList.stream().max((o1, o2) -> o1.getAge() - o2.getAge());
        System.out.println(max.get());

        6.1.8 reduce规约操作

public class Test05 {
    public static void main(String[] args) {
        Integer [] arr={2,3,4,5,6,2};

        //第一次赋值时,会把集合中的前两个元素赋值于t1 t2   后面会把方法计算的结果赋予t1  在集合的后面的元素赋予t2
        Optional<Integer> reduce = Arrays.stream(arr).reduce((t1, t2) -> t1+=t2);
        System.out.println(reduce.get());
    }
}

        6.2 collect搜集操作

        计数: count

        平均值: averagingInt、 averagingLong、 averagingDouble

        最值: maxBy、 minBy

        求和: summingInt、 summingLong、 summingDouble

    List<Person> personList = new ArrayList<>();
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("何雪",21,"中国",'F'));
        personList.add(new Person("李康",22,"中国",'M'));

//        Long collect =personList.stream().collect(Collectors.counting());
//        System.out.println(collect);
//        Double collect = personList.stream().collect(Collectors.averagingInt(item -> item.getAge()));
//        System.out.println(collect);
//        Optional<Person> collect = personList.stream().collect(Collectors.maxBy(((o1, o2) -> o1.getAge() - o2.getAge())));
//        System.out.println(collect);

        Integer collect = personList.stream().collect(Collectors.summingInt(item -> item.getAge()));
        System.out.println(collect);

        搜集为一个新的集合。

        List<Person> personList = new ArrayList<>();
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("何雪",21,"中国",'F'));

//        Set<String> set = personList.stream().filter(item -> item.getAge() > 20)
//                .filter(item -> item.getCountry().equals("中国"))
//                .map(item -> item.getName())
//                .collect(Collectors.toSet());
//        System.out.println(set);
        Map<String, Person> map = personList.stream().filter(item -> item.getAge() > 20)
                .filter(item -> item.getCountry().equals("中国"))
                .collect(Collectors.toMap(item -> item.getName(), item -> item));
        System.out.println(map);

        分组操作

        List<Person> personList = new ArrayList<>();
        personList.add(new Person("Tom",24,"美国",'M'));
        personList.add(new Person("欧阳雪",18,"中国",'F'));
        personList.add(new Person("Harley",22,"英国",'F'));
        personList.add(new Person("小梅",20,"中国",'F'));
        personList.add(new Person("向天笑",20,"中国",'M'));
        personList.add(new Person("李康",22,"中国",'M'));
        personList.add(new Person("何雪",21,"中国",'F'));

        Map<Character, List<Person>> collect = personList.stream().collect(Collectors.groupingBy(item -> item.getSex()));
        System.out.println(collect);

        七、JDK8中日期时间类

public class Test {
    public static void main(String[] args) {
//        //自定义时间的日期---设计不合理。
//        Date date=new Date(2022,11,5);
//        System.out.println(date);
//
//        //时间格式转化---存在线程安全问题
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        System.out.println(sdf.format(date));

        for (int i = 0; i <10 ; i++) {
               new Thread(new Runnable() {
                   @Override
                   public void run() {
                       try {
                           System.out.println(sdf.parse("2022-11-05"));
                       } catch (ParseException e) {
                           e.printStackTrace();
                       }
                   }
               }).start();
        }
    }
}

        日期时间类设计不合理---两个包下都有Date. Date的年需要从1900算起。

        日期转化类存在线程安全问题。

        jdk8后提供了新的日期时间类以及转化类。java.time包下

        7.1 日期时间

        

public class Test {
    public static void main(String[] args) {
        //创建一个指定日期时间的类
        LocalDateTime dateTime = LocalDateTime.of(2022, 10, 11, 17, 18, 16);
        //创建当前的日期时间对象
        LocalDateTime now = LocalDateTime.now();

        System.out.println("指定的日期时间:"+dateTime.toString());
        System.out.println("当前的日期时间:"+now);
    }

    private static void getTime(){
        //获取一个指定的时间
        LocalTime time = LocalTime.of(11, 11, 11);
        //获取当前的时间
        LocalTime now = LocalTime.now();
        System.out.println("指定的时间:"+time);
        System.out.println("当前的时间:"+now);

        //时间类中常用的方法
        System.out.println("获取时间的小时:"+now.getHour());
        System.out.println("获取时间的分钟:"+now.getMinute());
        System.out.println("获取时间的秒:"+now.getSecond());
        System.out.println("获取时间的纳秒:"+now.getNano());
    }
     private static void getDate(){
        //创建一个LocalDate日期类。--创建指定的日期
        LocalDate date = LocalDate.of(2022, 10, 7);
        //创建一个当前日期
        LocalDate now = LocalDate.now();

        System.out.println("指定的日期:"+date);
        System.out.println("当前日期:"+now);

        //日期类中的常见的方法
        System.out.println("获取日期的年份:"+now.getYear());
        System.out.println("获取日期的月份:"+now.getMonth().getValue());
        System.out.println("获取日期的星期:"+now.getDayOfWeek().getValue());
    }
}

        7.2 把日期时间转化为字符串和字符串解析为日期时间

        DateTimeFormate 可以进行日期时间和字符串的转化

                (1) 把日期时间转化为指定格式的字符串。  

public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        System.out.println("转化前的日期时间:"+now);
        DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");

        String format = now.format(dtf);
        System.out.println("转化后:"+format);
    }

        (2)把字符串转化为日期时间对象  

    public static void main(String[] args) {
        DateTimeFormatter dtf=DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        LocalDateTime dateTime = LocalDateTime.parse("2020/11/17 22:22:22", dtf);
        System.out.println(dateTime);
    }

        7.3 日期时间比较类.

                

public class Test {
    public static void main(String[] args) {
        LocalDate date = LocalDate.of(2020, 11, 1);
        LocalDate now = LocalDate.now();
        //比较两个日期的距离
        Period period = Period.between(date, now);
        System.out.println("相差的年:"+ period.getYears());
        System.out.println("相差的月:"+ period.getMonths());
        System.out.println("相差的天:"+ period.getDays());

        LocalTime time = LocalTime.of(8, 12, 12);
        LocalTime now1 = LocalTime.now();
        Duration between = Duration.between(time, now1);
        System.out.println(between.toHours());
        System.out.println(between.toMinutes()); //时间与时间之间相差的分钟
        System.out.println(between.getSeconds());//时间与时间之间相差的秒


    }
}
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值