java8新特性

发布于:2025-05-15 ⋅ 阅读:(18) ⋅ 点赞:(0)

1.Lambda

  • 匿名函数,Lambad表达式可以理解为一段可以传递的代码(将代码像数据一样传递)
  • 格式:
    • -> : lambda操作符
    • -> 左边: 形参列表(其实就是接口中的抽象方法的形参列表)
    • ->右边: lambda体(其实就是重写的抽象方法的方法体)
  • 使用:(六种情况)
    • 1.无参无返回值
    • 2.lambda需要一个参数,但是没有返回值
    • 3.数据类型可以省略,因为可由编辑器推断得出,称为"类型推断"
    • 4.只需要一个参数时,参数的小括号可以省略
    • 5.需要两个或以上的参数,多条执行语句,并且可以有返回值
    • 6.lambda只有1条语句时,return和{}都可以省略
    • 总结:
      • 左边:形参列表的参数类型可以省略(类型推断);如果只有一个参数,()也可以省略
      • 右边:lambda {}在只有一条语句时(可能是return语句)可以省略,return关键字也要省略
  • 本质:作为函数式接口的一个实例(一定是借助接口存在)
    • 接口是只能有一个抽象方法
    • 以前用匿名实现类表示的现在都可以用Lambda表达式来写
- 引入
package Lambda;

import org.junit.Test;

import java.util.Comparator;

public class LambdaTest {
@Test
    public void test1() {
        Runnable r1= new Runnable() {

            @Override
            public void run() {
                System.out.println("我爱北京天安门");
            }
        };
        r1.run();
        //---------------------------------------------
        Runnable r2= ()-> System.out.println("我爱北京天安门");
        r2.run();
    }

    @Test
    public void test2() {
    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer s1, Integer s2) {
            return Integer.compare(s1,s2);
        }
    };
     int res1=com1.compare(12,18);
        System.out.println(res1);

        System.out.println("**************");
        //Comparator接口中只有比较的这个方法,所以这些步骤可以是省略
        Comparator<Integer> com2 =  (s1, s2) -> Integer.compare(s1,s2);
        int res2=com2.compare(1282,181);
        System.out.println(res2);

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

        //更简洁写法:方法引用
        Comparator<Integer> com3 = Integer::compare;
        int res3=com2.compare(1282,181);
        System.out.println(res3);

    }
}

-----------------------------------------------------------------------------------------------------
package Lambda;

import org.junit.Test;

import java.util.Comparator;
import java.util.function.Consumer;

public class LambdaTest {
    @Test
    //1.无参无返回值
    public void test1() {
        Runnable r1 = new Runnable() {

            @Override
            public void run() {//看方法
                System.out.println("我爱北京天安门");
            }
        };
        r1.run();
        //---------------------------------------------
        System.out.println("------------------");
        Runnable r2 = () -> {
            System.out.println("我爱北京天安门");
        };
        r2.run();
    }

    //2.lambda需要一个参数,但是没有返回值
   @Test
    public void test2() {
       Consumer<String> con =new Consumer<String>() {
           @Override
           public void accept(String s) {
               System.out.println(s);
           }
       };
       con.accept("雅黑发放表");
       System.out.println("------------------");
      Consumer<String> con1 = (String s) -> {
          System.out.println(s);
      };
      con1.accept("哈哈哈哈");
    }

    //3.数据类型可以省略,因为可由编辑器推断得出,称为"类型推断"
    //在列表创建中可以知道
   @Test
    public void test3() {
       Consumer<String> con1 = (String s) -> {
           System.out.println(s);
       };
       con1.accept("哈哈哈哈");
       System.out.println("------------------");
       Consumer<String> con2 = (s) -> {//类型推断,可以省略
           System.out.println(s);
       };
       con2.accept("哈哈哈哈");

   }
   //4.只需要一个参数时,参数的小括号可以省略
   @Test
    public void test4() {
       Consumer<String> con1 = (s) -> {//类型推断,可以省略
           System.out.println(s);
       };
       con1.accept("哈哈哈哈");
       System.out.println("-----------------------------");
       Consumer<String> con3 = s -> {//少了小括号
           System.out.println(s);
       };
       con3.accept("哈哈哈哈");
   }

   //5.需要两个或以上的参数,多条执行语句,并且可以有返回值
   @Test
    public void test5() {
       Comparator<Integer> com1 = new Comparator<Integer>() {
           @Override
           public int compare(Integer o1, Integer o2) {
               System.out.println(o1);
               System.out.println(o2);
               return o1.compareTo(o2);
           }
       };

       System.out.println(com1.compare(1,3));
       System.out.println("-----------------------------");
       Comparator<Integer> com2= (o1,o2) ->{
           System.out.println(o1);
           System.out.println(o2);
           return o1.compareTo(o2);
       };
       System.out.println(com2.compare(12,3));
   }

   //6.lambda只有1条语句时,return和{}都可以省略
   @Test
    public void test6() {
       Comparator<Integer> com1= (o1,o2) ->{
           return o1.compareTo(o2);
       };
       System.out.println(com1.compare(12,3));

       System.out.println("-----------------------------");
       Comparator<Integer> com2= (o1,o2) ->o1.compareTo(o2);

       System.out.println(com2.compare(12,3));
   }
   @Test
   public void test7() {
       Consumer<String> con1 = (s) -> {//类型推断,可以省略
           System.out.println(s);
       };
       con1.accept("哈哈哈哈");
       System.out.println("-----------------------------");
       Consumer<String> con3 = s ->  System.out.println(s);
       con3.accept("哈哈哈哈");
   }
}

2.函数式接口

  • 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口
  • 在接口上使用@FunctionalInterface注解,这样做可以检查它是否是一个函数式接口,同时javadoc也会包含一条声明,说明这个接口是一个函数式接口
  • 何时使用函数式接口
    • 如果我们开发中需要定义一个函数式接口,首先看看在已有的jdk提供的函数式接口是否提供了能满足需求的函数式接口 ,如果有直接调用,不需要自己定义了
  • 在这里插入图片描述- 自定义函数式接口
package Lambda;

@FunctionalInterface
public interface MyInterface {
    void method1();
}

  • java内置四大核心函数式接口
函数式接口 参数类型 返回类型 用途
Consumer 消费型接口 T void 对对象为T的对象应用操作, 包含方法 : void accept(T t)
Supplier供给型接口 T 返回类型为T的对象,包含方法: T get()
Function<T,R> 函数型 T R 对对象为T的对象应用操作,并返回结果.结果是R类型的对象,包含方法: R apply(T t)
Predicate 断定型 T bollean 确定对象是否满足约束,并返回boolean值.包含方法:boolean test(T t)
package Lambda;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**java 内置4大核心函数式接口
 * 1.消费型接口 Consumer<T>  void accept(T t)
 * 2.供给型接口 Supplier<T>  T get()
 * 3.函数型接口 Function<T,R> R apply(T t)
 * 4.断言型接口 Predicate<T> boolean test(T t)
 */
public class LambdaFunctionTest {
    @Test
    public void test1(){
        happyTime(100,new Consumer<Double>(){

            @Override
            public void accept(Double aDouble) {
                System.out.println("消费"+aDouble);
            }
        });
        System.out.println("*******************************");

        happyTime(100,money -> System.out.println("消费"+money));

    }

    public void happyTime(double money, Consumer<Double> con){
        con.accept(money);
    }

    @Test
    public void test2(){
        List<String> list = Arrays.asList("aaa","bb","ccc","ddd");
        List<String> filterString =
        filterString(list, new Predicate<String>() {
            @Override
            public boolean test(String s) {

                return s.length() > 2;
            }
        });
        System.out.println(filterString);
        System.out.println("*******************************");
        
        List<String> filterString2 =filterString(list,s -> s.length() <3);
        System.out.println(filterString2);

    }
    //根据给定的规则,过滤结合汇总的字符串,此规则由Predicate的方法决定
    public List<String> filterString(List<String> list, Predicate<String> pre){//集合根据某种规则来做一个过滤
        ArrayList<String> filterList= new ArrayList<>();
        for(String s:list){
            if(pre.test(s)){
                filterList.add(s);
            }
        }
        return filterList;
    }
}

  • 在这里插入图片描述

3.方法应用和构造器引用

  • 使用情景:当要传递个Lambda体的操作,已经有实现的方法了,可以使用方法引用
  • 可以看做Lambda表达式的深层次的表达
  • 本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例,所以方法引用也是函数表达式的接口
  • 使用: ==类/对象 : : 调用的方法名 ==
  • 分三种情况:
    • 对象 : : 非静态方法
    • 类 : : 非静态方法
    • 类 : : 静态方法
  • 要求:
    • 要求接口中的抽象方法的形参列表和返回值类型 与方法引用的方法的形参列表和返回值类型相同(情况1,2)
    • 当函数式接口方法的第一个参数是需要引用方法的调用者,并且第二个参数是需要引用地方免费参数(或无参数)时:ClassName::methodName(情况3)
方法引用
package MethodTest;

import org.junit.Test;

import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

public class MethodTest {
    //1.对象 :: 实例方法

    //Consumer 中的void accept(T,t) 接口中的形参列表返回类型
    //PrintStream中的void println(T t) 与这个类的形参列表返回类型一致
    @Test
    public void test1() {
        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("哈哈");

        System.out.println("--------------------------------");
        PrintStream ps=System.out;//对象//非静态方法用对象去调用
        Consumer<String> con2 = ps::println;
        con2.accept("呵呵");
    }
    //Supplier 中的 T get()
    //Employee 中的String getName()
    @Test
    public void test2(){//什么也不放,但是返回值
        Employee emp = new Employee(1,"QQ",23,000);
        Supplier<String> sup1 = () -> emp.getName();//对象//非静态方法用对象去调用
        System.out.println(sup1.get());
        System.out.println("--------------------------------");
        Supplier<String> sup2 = emp::getName;
        System.out.println(sup2.get());
        //本身这个方法有一个抽象方法已经实现,而且参数列表返回类型一样
    }

    //2.类 :: 静态方法
    //Comparator 中的int compare(T t1,T t2)
    //Integar 中的int compare(T t1,T t2)
    @Test
    public void test3(){
        Comparator<Integer> com1= (t1, t2) -> Integer.compare(t1,t2);
        System.out.println(com1.compare(12,21));

        System.out.println("--------------------------------");
        Comparator<Integer> com2 = Integer::compare;//不用写括号方原因是因为,参数与形参列表的参数一样
        System.out.println(com2.compare(12,21));
    }

    //Function 中的 R apply(T t)
    //Math 中的Long  round(double d)
    @Test
    public void test4(){
        Function<Double ,Long> funn2 = new Function<Double, Long>() {
            @Override
            public Long apply(Double d) {
                return Math.round(d);
            }
        };
        Function<Double,Long> func1 = d-> Math.round(d);
        System.out.println(func1.apply(12.3));
        System.out.println("--------------------------------");
        Function<Double,Long> func2 = Math::round;
        System.out.println(func2.apply(12.3));

    }

    //3.类 :: 实例方法 (难)
    //Comparator 中的int compare(T t1,T t2)
    //String 中的int t1.compareTo(t2) //变为调用者
    @Test
    public void test5(){
        Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
        System.out.println(com1.compare("abc","abd"));
        System.out.println("--------------------------------");
        Comparator<String> com2 = String::compareTo;
        System.out.println(com2.compare("abc","abm"));
    }
    //BiPrecdicate 中的boolean test(T t1,T t2)
    //String 中的boolean t1.equals(t2)
    @Test
    public void test6(){
        BiPredicate<String,String> bp1 = (s1, s2) -> s1.equals(s2);
        System.out.println(bp1.test("abc","abc"));
        System.out.println("--------------------------------");
        BiPredicate<String,String> bp2 = String::equals;
        System.out.println(bp2.test("abc","abc"));
    }
    //Function 中的R apply(T t)
    //Employee 中的String getName()
    @Test
    public void test7(){
        Employee employee = new Employee(1001,"hh",12,120.1);
        Function<Employee,String> fun1 = (e) -> e.getName();
        System.out.println(fun1.apply(employee));
        System.out.println("--------------------------------");
        Function<Employee,String> fun2 = Employee::getName;
        System.out.println(fun2.apply(employee));
    }
}



构造器引用
package MethodTest;

import org.junit.Test;

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

/**
 * 1.构造器引用
 *      和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一样
 *      抽象方法的返回值类型即为构造器所属的类的类型
 * 2.数组引用
 *      可以把数组看做应该特殊的类,则写法与构造器引用一样
 *
 */
public class ConstructtoRefTest {
    //构造器引用 类名::new
    //Supplier 中的T get()
    //无参有返回值
    //Employee的空参构造器 :Employee()

    //抽象方法有一个返回值T,T就是要创建的类型的对象
    @Test
    public void test1() {
        Supplier<Employee> sup = new Supplier<Employee>() {


            @Override
            public Employee get() {
                return new Employee();
            }
        };
        System.out.println("*************************");

        Supplier<Employee> sup1 = () -> new Employee();
        System.out.println(sup1.get());
        System.out.println("*************************");
        Supplier<Employee> sup2 = Employee::new;
        System.out.println(sup2.get());


    }

    //Function 中的R apply(T t)
    @Test
    public void test2() {
        Function<Integer, Employee> fun1 = id -> new Employee(id);
        Employee employee = fun1.apply(1001);
        System.out.println(employee);
        System.out.println("*************************");
        Function<Integer, Employee> fun2 = Employee::new;
        Employee employee1 = fun2.apply(1002);
        System.out.println(employee1);
    }
    //BiFunction 中的R apply(T t,U u)

    @Test
    public void test3() {
        BiFunction<Integer, String, Employee> fun1 = (id, name) -> new Employee(id, name);
        System.out.println(fun1.apply(1001, "Tom"));
        System.out.println("*************************");
        BiFunction<Integer, String, Employee> fun2 = Employee::new;
    }

    //2.数组引用 数组类型[] :: new
    @Test
    public void test4() {
        //长度
        Function<Integer, String[]> fun1 = length -> new String[length];
        String[] arr1 = fun1.apply(10);
        System.out.println(Arrays.toString(arr1));
        System.out.println("*************************");
        Function<Integer, String[]> fun2 = String[]::new;
        String[] arr2 = fun2.apply(20);
        System.out.println(Arrays.toString(arr2));
    }
}

4.StreamAPI

在这里插入图片描述

  • Stream与Collection集合的区别:Collection是一种静态的内存数据机构,面向内存,存储在内存中;Stream是有关于计算,面向CPU,通过CPU实现计算.
  • 注意:
    • Stream不会自己存储元素

    • 不会改变源对象,会返回一个持有结果的新Stream

    • 操作是延迟执行的,意味着他们会等到需要结果的时候才执行

    • 步骤:

    • 1.创建Stream

      • 一个数据源(如:集合,数组),获取一个流
    • 2.中间操作

      • 一个中间操作(过滤,映射等)链,对数据源的数据进行处理
      • 在这里插入图片描述
      • 在这里插入图片描述
      • 在这里插入图片描述
    • 3.终止操作

      • 一旦执行终止操作,就执行中间操作链,并产生结果,之后就不会再被使用
      • 在这里插入图片描述
      • 在这里插入图片描述
      • 在这里插入图片描述
      • 在这里插入图片描述
package StreamAPI;
//1.对数据的运算,与CPU
//集合对数据的存储,与内存

import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 *
 */
public class StreamTest {
    //创建方式:
//    1.通过集合
    //default Stream<E> stream() :返回一个顺序流
    //default Stream<E> parallelStream() :返回一个并行流
    @Test
    public void test1(){
        List<Employee> employees = EmployeeData.getEmployees();
        //返回一个顺序流
        Stream<Employee> stream = employees.stream();

        //返回一个并行流
        Stream<Employee> parallelStream = employees.parallelStream();

    }
//    2.通过数组
     //调用Arrays类中的static <T> Stream<T> stream(T[] array):返回一个流
    //通过泛型来识别类型
    @Test
    public void test2(){
        int[] arr = new int[]{1,2,3,4,5,6};
        IntStream stream =Arrays.stream(arr);
        Employee e1= new Employee(1001,"Tom",23,5600);
        Employee e2= new Employee(1002,"Jerry",34,6600);
        Employee[] arr1 = new Employee[]{e1,e2};//静态初始化
        Stream<Employee> stream1 = Arrays.stream(arr1);
    }

    //    3.通过Stream的of()
    @Test
    public void test3(){
        Stream<String> stream = Stream.of("aa", "bb", "cc", "dd");//包装类对象
    }

    //    4.创建无限流(不常用)
    //4.1 迭代
    //public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
    //4.2 生成
    //public static<T> Stream<T> generate(Supplier<T> s)
    @Test
    public void test4(){
        //迭代
        //遍历前10个偶数
        Stream.iterate(0,t-> t+2).limit(10).forEach(System.out::println);
        //生成
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }
}
---------------------------------------------------------------------------------------------------------------------------------------------
package StreamAPI;

import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;

import java.util.List;
import java.util.stream.Stream;

/**
 * 测试Stream的中间操作
 */
public class StreamTest1 {
    //1.筛选与切片
    /**
     * filter(Predicate p)——接收Lambda,从流中排除某些元素
     * limit(long maxSize)——截断流,使其元素不超过给定数量
     * skip(long n)——跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补
     * distinct()——筛选,通过流所生成元素的hashCode()和equals()去除重复元素
     */
//    1.1filter
    @Test
    public void test1(){
        List<Employee> list = EmployeeData.getEmployees();
        Stream<Employee> stream= list.stream();
        //查询员工表>1000
        stream.filter(e->e.getSalary()>1000).forEach(System.out::println);
        //一旦执行终止操作,stream流就会关闭,不可以再次使用
//     1.2limit()
        System.out.println("limit()----------------");
        //重新调用
        list.stream().limit(3).forEach(System.out::println);
//     1.3skip()//跳过前面的数据
        System.out.println("skip()----------------");
        list.stream().skip(3).forEach(System.out::println);
//     1.4distinct()//去 重
        System.out.println("distinct()----------------");
        list.add(new Employee(1010,"张三",23,9999.99));
        list.add(new Employee(1010,"张三",23,9999.99));
        list.add(new Employee(1010,"张三",23,9999.99));
        list.add(new Employee(1010,"张三",23,9999.99));
        list.add(new Employee(1010,"张三",23,9999.99));

        list.stream().distinct().forEach(System.out::println);
    }

}
---------------------------------------------------------------------------------------------------------------------------------------------
package StreamAPI;
//2.映射

import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * map(Function f) 接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数,会被应用到每个元素上,并将其映射成一个新的元素
 * flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
 */
public class StreamTest2 {
    //map(Function f) 接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数,会被应用到每个元素上,并将其映射成一个新的元素
    //类似于add
    @Test
    public void test1(){
            List<String> list= Arrays.asList("aaa","bbb","ccc");
            list.stream().map(str->str.toUpperCase()).forEach(System.out::println);

        System.out.println("----------------");
            List<Employee> employees= EmployeeData.getEmployees();
            //练习1.获取员工姓名长度 的员工姓名
                   Stream<String> nameStream=employees.stream().map(Employee::getName);
            nameStream.filter(name ->name.length()>3).forEach(System.out::println);
        System.out.println("----------------");

            //练习2
            Stream<Stream<Character>> streamStream=list.stream().map(StreamTest2::fromStringToStream);
            streamStream.forEach(s->s.forEach(System.out::println));
        System.out.println("----------------");
            //flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
            //类似于addALl
           Stream<Character> characterStream = list.stream().flatMap(StreamTest2::fromStringToStream);
           characterStream.forEach(System.out::println);

    }

    @Test
    public void test2(){

    }

     @Test
    public void test3(){
        ArrayList  list1=new ArrayList();
        list1.add(1);
        list1.add(2);
        ArrayList list2=new ArrayList();
        list2.add(3);
        list2.add(4);

//        list1.add(list2);
        list1.addAll(list2);
        System.out.println(list1);

    }
    //将字符串中的多个字符构成的集合转换为响应的Stream的实例
    public static Stream<Character> fromStringToStream(String str){
        ArrayList<Character> list = new ArrayList<>();
        for (Character c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }

}
--------------------------------------------------------------------------------------------------------------------------------------------
package StreamAPI;

import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

//3.排序

/**
 * sorted() 自然排序
 * sorted(Comparator com) 定制排序
 */
public class StreamTest3 {
    @Test
    public void test1(){
        //sorted
        List<String> list = Arrays.asList("ccc","aaa","bbb","ddd","eee");
        list.stream().sorted().forEach(System.out::println);
//抛异常,原因:Employee没有实现Comparable接口
//        List<Employee> employees = EmployeeData.getEmployees();
//        employees.stream().sorted().forEach(System.out::println);
//
        List<Employee> employees = EmployeeData.getEmployees();
//        employees.stream().sorted((e1,e2) ->{
//                return Integer.compare(e1.getAge(),e2.getAge());
//        }).forEach(System.out::println);
        employees.stream().sorted((e1,e2) ->Integer.compare(e1.getAge(),e2.getAge())).forEach(System.out::println);
        System.out.println("--------------------------");
        //年龄一样,按照薪水来比较
        employees.stream().sorted((e1,e2) -> {
            int result = Integer.compare(e1.getAge(), e2.getAge());
            if (result != 0) {
                return result;
            } else {
                return Double.compare(e1.getSalary(), e2.getSalary());
            }
        }).forEach(System.out::println);
        }
}
--------------------------------------------------------------------------------------------------------------------------------------------
package StreamAPI;

import MethodTest.Employee;
import MethodTest.EmployeeData;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
//1.匹配与查找
//1.1 allMatch(Predicate p)——检查是否匹配所有元素
//练习:是否所有员工的年龄都大于18\
//1.2 anyMatch(Predicate p)——检查是否至少匹配一个元素
//练习:是否存在员工的工资大于10000
//1.3 noneMatch(Predicate p)——检查是否没有匹配的元素
//练习:是否不存在员工姓王
//1.4 findFirst()——返回第一个元素
//1.5 findAny()——返回当前流中的任意元素
//1.6 count()——返回流中元素的总个数
//1.7 max(Comparator c)——返回流中最大值
//        练习:返回最高的工资
//1.8 min(Comparator c)——返回流中最小值
//练习:返回最低的工资
//1.9 foreach(Consumer c)——内部迭代



public class StreamEndTest1 {
    @Test
    public void test1(){
        List<Employee> employees = EmployeeData.getEmployees();

        //1.1allMatch(Predicate p)——检查是否匹配所有元素
        //练习:是否所有员工的年龄都大于18
        boolean allMatch = employees.stream().allMatch(e->e.getAge()>18);
        System.out.println(allMatch);
        //1.2anyMatch(Predicate p)——检查是否至少匹配一个元素
        //练习:是否存在员工的工资大于10000
        boolean anyMatch = employees.stream().anyMatch(e->e.getSalary()>1000 );
        System.out.println(anyMatch);
        //1.3noneMatch(Predicate p)——检查是否没有匹配的元素
        //练习:是否不存在员工姓王
        boolean noneMatch = employees.stream().noneMatch(e->e.getName().startsWith("王"));
        System.out.println(noneMatch);
        //1.4findFirst()——返回第一个元素
        Optional<Employee> first = employees.stream().findFirst();
        System.out.println(first);
        //1.5findAny()——返回当前流中的任意元素
        Optional<Employee> any1 = employees.stream().findAny();//串行流,从第一个取
        Optional<Employee> any2 = employees.parallelStream().findAny();//并行流,从任意一个取
        System.out.println(any1+"\n"+any2);



    }
    @Test
    public void test2(){
        //1.6count()——返回流中元素的总个数
        List<Employee> employees = EmployeeData.getEmployees();
        long count = employees.stream().filter(e->e.getSalary()>5000).count();
        System.out.println(count);
        //1.7max(Comparator c)——返回流中最大值
        //练习:返回最高的工资
        Stream<Double> salaryStream = employees.stream().map(e -> e.getSalary());
        Optional<Double> max1 = salaryStream.max(Double::compare);
        Optional<Employee> max2 = employees.stream().max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(max1+"\n"+max2);
        //1.8min(Comparator c)——返回流中最小值
        //练习:返回最低工资的员工
        Optional<Employee> employee=employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(employee);
        Optional<Double> min = employees.stream().map(Employee::getSalary).min(Double::compare);
        System.out.println(min);
        //1.9forEach(Consumer c)——内部迭代
        //使用方法引用
        employees.stream().forEach(System.out::println);
        //使用集合的遍历
        employees.forEach(System.out::println);

        //2.

    }
    //2.归约
    //2.1 reduce(T identity,BinaryOpretor) 可以将流中元素反复结合起来,得到一个值,返回T
    //练习:计算1-10的自然数的和
    //2.2 reduce(BinaryOpretor) 可以将流中元素反复结合起来,得到一个值,返回 Optional<T>
    //练习:计算公司所有员工工资的总和
    @Test
    public void test3(){
        //2.1 reduce(T identity,BinaryOpretor) 可以将流中元素反复结合起来,得到一个值,返回
        //练习:计算1-10的自然数的和
        List<Integer> lsit= Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer sum = lsit.stream().reduce(0, Integer::sum);//Integer有个静态方法,sum传两个参数;函数式接口reduce也是传入两个参数
        System.out.println(sum);
        //2.2 reduce(BinaryOpretor) 可以将流中元素反复结合起来,得到一个值,返回 Optional<T>
        //练习:计算公司所有员工工资的总和
        List<Employee> employees = EmployeeData.getEmployees();
        Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);
//        Optional<Double> sumMoney=salaryStream.reduce(Double::sum);
        Optional<Double> sumMoney=salaryStream.reduce((d1,d2)->d1+d2);
        System.out.println(sumMoney);
    }

    //3.收集
    //collect 将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
    @Test
    public void test4(){
        //练习:查找工资大于6000的员工,结果返回为一个List(有序)或Set(无序)
        List<Employee> employees = EmployeeData.getEmployees();
        List<Employee> employeeList =employees.stream().filter(e->e.getSalary()>6000).collect(Collectors.toList());
        employeeList.forEach(System.out::println);
        System.out.println("---------------------------");
        Set<Employee> employeeSet =employees.stream().filter(e->e.getSalary()>6000).collect(Collectors.toSet());
        employeeSet.forEach(System.out::println);

}}


5.Optional类

在这里插入图片描述
在这里插入图片描述

package OptionalTest;

import org.junit.Test;

import java.util.Optional;

/**
 * Optional类:用于解决空指针异常的问题,为了不出现空指针出现异常而创建的
 *
 * Optional.of(T t) : 创建一个 Optional 实例,t 不能为 null
 * Optional.empty() : 创建一个空的 Optional 实例
 * Optional.ofNullable(T t) : t 可以为 null
 */
public class OptionalTest {
    @Test
    public void test1(){
        Girl girl= new Girl("哈哈");
//        girl = null;
        //of(T t) 方法必须保证t不能为空,否则报空指针异常
        Optional<Girl> optionalGirl =Optional.of(girl);
        System.out.println(optionalGirl);
    }
    @Test
    public void test2(){
        Girl girl= new Girl("哈哈");
//        girl = null;
        //ofNullable(T t) 方法t可以为空
        Optional<Girl> optionalGirl =Optional.ofNullable(girl);
        System.out.println(optionalGirl);
        //orElse(T t1) 方法如果optionalGirl内部封装的t是非空,则返回内部的t;
        // 如果内部的t为空,则返回orElse()方法中的参数t1
        Girl girl1 = optionalGirl.orElse(new Girl("哈哈"));
        System.out.println(girl1);
    }
    @Test
    public void test3(){
        Girl girl= new Girl("哈哈");
        girl = null;
        //empty() 方法创建一个空的 Optional 实例
        Optional<Girl> optionalGirl =Optional.empty();
        System.out.println(optionalGirl);
    }
        public String getGirlName1(Boy boy){
            return boy.getGirl().getName();
        }
        @Test
        public void test4(){
            Boy boy = new Boy();
            String girlName = getGirlName1(boy);
            System.out.println(girlName);//NullPointerException
        }
        //优化以后
        public String getGirlName2(Boy boy){
            if(boy != null){
                Girl girl = boy.getGirl();
                if (girl !=null){
                    return girl.getName();
                 }
            }
            return null;
        }
        @Test
        public void test5(){
            Boy boy = new Boy();
            String girlName = getGirlName2(boy);
            System.out.println(girlName);//NullPointerException

        }

        //典型练习,保证如下的方法执行中不会出现空指针异常
    //使用Optional类优化以后
    public String getGirlName3(Boy boy){

        Optional<Boy> optionalBoy = Optional.ofNullable(boy);
        //此时boy1一定非空
        Boy boy1 = optionalBoy.orElse(new Boy(new Girl("呵呵")));//orElse方法,如果为空,就返回一个默认值
        Girl girl = boy1.getGirl();

        Optional<Girl> girlOptional=Optional.ofNullable(girl);//不空就是本身数据
        Girl girl1 = girlOptional.orElse(new Girl("嘿嘿"));//为空就是orElse()中的数据
        //girl1一定非空
        return girl1.getName();
    }
    @Test
    public void test6(){
        Boy boy = null;
        boy = new Boy();
        boy= new Boy(new Girl("嘻嘻"));

        String girlName = getGirlName3(boy);
        System.out.println(girlName);//哈哈
    }
}
----------------------------------------------------------------------
package OptionalTest;


import org.junit.Test;

import java.util.Optional;

public class OptionalTest1 {
    @Test
    public void test1() {
        Optional<Object> op1 = Optional.empty();
//        if (op1.isPresent()){//Optional封装的数据是否为空
        if (!op1.isPresent()) {//Optional封装的数据是否包含数据
            System.out.println("数据为空");

        }
        System.out.println(op1);
        System.out.println(op1.isPresent());
        //如果Optional封装的数据为空,则get()报错;如果不为空,则返回参数值
//        System.out.println(op1.get());

    }

    @Test
    public void test2() {
        String str = "hello";
        str= null;
        //Optional.ofNullable(str);//允许为空
        //of(T t)方法要求传入的参数t不能为空,如果为空,会抛出NullPointerException
        Optional<String> op1 = Optional.of(str);
        //明确不是空使用 get() 和 of()
        //get()通常与of()方法搭配,用于获取内部的封装的数据
        String str1 = op1.get();
        System.out.println(str1);
    }
    @Test
    public void test3() {
        //有可能为空,使用
        //ofNullable和orElse
        String str ="哈哈";
        //ofNullable(T t)封装数据t赋给Optional内部的value,不要求t非空
//        Optional<String> op1 = Optional.ofNullable(str);
        Optional<String> op1 = Optional.ofNullable(null);
        //orElse(T t1)方法,如果Optional封装的数据为空,则返回参数t
        //value为空,则返回t1
        String str1 = op1.orElse("默认值");
        System.out.println(str1);
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到