Java8的一些新特性

Java8的一些新特性

1、函数式接口

函数式接口:是Lambda表达式的基础,

什么是函数式接口?(它就是一个只有一个抽象方法的接口,通常我们会在这个接口上用一个@FunctionalInterface注解来验证这个接口是不是函数式接口)

2、Lambda表达式

2.1、介绍

它其实是一种新的java语法格式:用于实现函数式接口中的抽象方法的,->这就是lambda表达式的标识符,所以我们也叫lambda表达式为箭头函数,其实lambda在java中并不是以函数的方式存在的,java语言的核心理念是万物基于对象,所以lambda表达式的作用就被实现接口的一个匿名对象

2.2、案例
/**
 * 函数式接口 即:该接口只有一个抽象方法
 */
@FunctionalInterface
public interface MyInterfaceTest {
    public void showInfo(String str);
}
**
 * Lambda表示使用:基于函数式接口的
 */
public class LambdaDemo1 {
    /**
     * 实现自定义的抽象接口
     */
    @Test
    public void test3() {
        //传统方式
        MyInterfaceTest interfaceTest = new MyInterfaceTest() {
            @Override
            public void showInfo(String str) {
                System.out.println(str);
            }
        };
        interfaceTest.showInfo("no give uo,no lost");

       System.out.println("==================");
       //lambda方式
        //这里是很简洁的写法
       MyInterfaceTest myInterfaceTest=str -> System.out.println(str);
       myInterfaceTest.showInfo("no zuo no die");

    }
2.3、案例讲解

上面就是一个很简单的lambda表达式的案例,函数式接口没什么好说的,传统的接口匿名内部类对象的写法也没什么好说的,这还是重点看一下lambda表达式为啥能这么写,有哪些规则

  1. 因为是函数式接口,接口中就这一个抽象方法,那么方法名是不是就默认就是它了,此时方法名就被省略了
  2. showInfo方法的形参有一个lambda中一个形参可以写str->或者(str)->,但是如果是多个形参或者空参就必须要加()
  3. 返回值,这里showInfo没有返回值,所以直接写了一条输出语句,(如果表达式中只有一条语句需要执行,就都可以这么写,也不能在前面指定retrun
  4. 方法体中的代码逻辑,因为只要一条语句需要执行所以省略了{}和return的判断由系统自己判断有没有返回,如果执行多条语句就必须添加{}如果有返回值也最好是写上return.

3、方法引用

3.1、介绍
方法引用其实是另外一种lambda的方式,本质上还是lambda
只是自己不再去实现函数式接口的方法,而是引用另外一个类的方法来实现接口
前提:
1.引用的方法的返回类型和形参类型以及个数必须一样(这只是针对,类调用静态方法和对象调用非静态的方法才有这么严格的要求)
2.引用的方法实现的功能必须和接口中需要实现的方法功能一样,不然你老婆叫你打酱油,你能打醋回去?
3.还有一种使用方式是,类调用非静态方法,这时候,对形参的个数要求就不那么严格了
3.2、案例
/**
     * 对象调用非静态方法
     */
    @Test
    public void test1() {
        //正常的lambda方式
        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("今朝有酒今朝醉");
        //方法引用,有一个类PrintStream 中有个void println(T t)方法也是输出语句,这就就用来代替我们自己的实现
        PrintStream ps = System.out;
        Consumer<String> con2 = ps::println;
        con2.accept("天若有情天亦老");
    }


    /**
     * 类调用静态方法
     */
    @Test
    public void test2() {
        //正常的lambda方式
        Comparator<Integer> comparator = (t1, t2) -> Integer.compare(t1, t2);
        int compare = comparator.compare(12, 13);
        System.out.println(compare);
        //方法引用
        Comparator<Integer> comparator1 = Integer::compare;
        int compare1 = comparator1.compare(12, 17);
        System.out.println(compare1);
    }

    /**
     * 类调用非静态方法
     */

    @Test
    public void test3() {
        Comparator<String> comparator = String::compareTo;
        System.out.println(comparator.compare("abc", "abd"));
        Function<Person,String> stringSupplier = Person::getName;
        Person person = new Person();
        person.setName("海子");
        System.out.println(stringSupplier.apply(person));
    }

4、StreamApi

4.1、介绍

StreamApi是java8中一个很重要的更新,目前用的也很多用了就回不去了。

StreamApi是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,Stream讲的是计算!”

注意:
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

4.2、Stream流操作的三个步骤
1- 创建Stream

​ 一个数据源(如:集合、数组),获取一个流

2- 中间操作

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

3- 终止操作(终端操作)
4.3案例
/**
 * java8的StreamAPI 的学习案例
 */
public class StreamAPIDemo {
    List<Person> personList = new ArrayList<>();
    Person p1= new Person("胡歌",18,100.000);
    Person p2= new Person("许嵩",16,109.000);
    Person p3= new Person("刘亦菲",18,100.00000);
    Person p4= new Person("薛之谦",20,10010.00);
    Person p5= new Person("霍建华",18,100.0100);
    Person p6= new Person("霍建华",18,100.0100);
    @Test
    public void test1(){
        personList.add(p1);
        personList.add(p2);
        personList.add(p3);
        personList.add(p4);
        personList.add(p5);
        //创建流
        Stream<Person> stream = personList.stream(); //还有parallelStream流这个是并行流,会并行去读取list里面的数据
        //filter中间操作(过滤数据)forEach终止操作迭代遍历数据
        stream.filter(p->p.getAge()>18).forEach(System.out::println); 

        System.out.println("====================");
        //distinct中间操作去重
        personList.stream().distinct().forEach(System.out::println);

        System.out.println("====================");
        //中间操作截断流从头开始到n
        personList.stream().limit(3).forEach(System.out::println);

        System.out.println("====================");
        //中间操作 跳过元素,返回一个扔掉了前n 个元素的流。若流中元素不足n 个,则返回一个空流。与limit(n) 互补
        personList.stream().skip(3).forEach(System.out::println);
    }

    @Test
    public void test2(){
        personList.add(p1);
        personList.add(p2);
        personList.add(p3);
        personList.add(p4);
        personList.add(p5);
        personList.stream().map(person -> person.getAge()).forEach(System.out::println);

        System.out.println("====================");
        DoubleStream doubleStream = personList.stream().mapToDouble(p -> p.getMoney());
        doubleStream.limit(3).forEach(System.out::println);
    }

    @Test
    public void test3(){
        personList.add(p1);
        personList.add(p2);
        personList.add(p3);
        personList.add(p4);
        personList.add(p5);
        System.out.println("=============================");
        boolean b = personList.stream().allMatch(p -> p.getName() == "刘亦菲");
        System.out.println(b);

        System.out.println("=============================");
        boolean b2 = personList.stream().anyMatch(p -> p.getName() == "刘亦菲");
        System.out.println(b2);

        System.out.println("=============================");
        boolean b3 = personList.stream().noneMatch(p -> p.getName() == "haizi");
        System.out.println(b3);

        System.out.println("=============================");
        Optional<Person> b4 = personList.stream().findFirst();
        System.out.println(b4);
    }


    @Test
    public void test4(){
        personList.add(p1);
        personList.add(p2);
        personList.add(p3);
        personList.add(p4);
        personList.add(p5);
        System.out.println("=============================");
        List<String> list = personList.stream().map(p -> p.getName()).collect(Collectors.toList());
        list.forEach(System.out::println);
        String collect = personList.stream().map(person -> person.getName())
                .collect(Collectors.joining("-","用户名:","所有都在这里了"));

        System.out.println("=============================");
        System.out.println(collect);
    }

}
4.4、案例讲解
  1. 创建流

    1. java8 中的Collection 接口被扩展,提供了两个获取流
      的方法:
      default Stream<E> stream(): 返回一个顺序流
      default Stream<E> parallelStream() : 返回一个并行流

    2. Java8 中的Arrays 的静态方法stream() 可以获取数组流:

      static <T> Stream<T> stream(T[] array): 返回一个流

      重载形式,能够处理对应基本类型的数组:
      public static IntStream stream(int[] array)

      public static LongStream stream(long[] array)
      public static DoubleStream stream(double[] array)

    3. 通过Stream的of()
      可以调用Stream类静态方法of(), 通过显示值创建一个 流。它可以接收任意数量的参数。

    public static<T> Stream<T> of(T... values): 返回一个流

    1. 创建无限流

      可以使用静态方法Stream.iterate()Stream.generate(), 创建无限流。
      迭代public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)

      生成public static<T> Stream<T> generate(Supplier<T> s)

      @Test
      public void test4() {
      // 迭代
      // public static<T> Stream<T> iterate(final T seed, final
      // UnaryOperator<T> f)
      Stream<Integer> stream = Stream.iterate(0, x -> x + 2);
      stream.limit(10).forEach(System.out::println);
      // 生成
      // public static<T> Stream<T> generate(Supplier<T> s)
      Stream<Double> stream1 = Stream.generate(Math::random);
      stream1.limit(10).forEach(System.out::println);
      
      }
      
    2. Stream 的中间操作

      1. 筛选与切片
        在这里插入图片描述

      2. 映射
        在这里插入图片描述

      3. 排序
        在这里插入图片描述

  2. Stream的终止操作

    终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例
    如:List、Integer,甚至是void 。流进行了终止操作后,不能再次使用。

    1. 匹配与查找

    在这里插入图片描述
    在这里插入图片描述
    2. 归约

    在这里插入图片描述

    1. 收集

    在这里插入图片描述
    4. Collectors工具类的方法

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

5、Optional类

5.1介绍

到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。 Optional<T>类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常。 Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gnASnbSo-1596987873418)(assets/optional%E6%96%B9%E6%B3%95.png)]

5.2、案例

@Test
public void test1() {
	Boy b = new Boy("张三");
	Optional<Girl> opt = Optional.ofNullable(b.getGrilFriend());
	// 如果女朋友存在就打印女朋友的信息
	opt.ifPresent(System.out::println);
}

@Test
public void test2() {
	Boy b = new Boy("张三");
	Optional<Girl> opt = Optional.ofNullable(b.getGrilFriend());
	// 如果有女朋友就返回他的女朋友,否则只能欣赏“嫦娥”了
	Girl girl = opt.orElse(new Girl("嫦娥"));
	System.out.println("他的女朋友是:" + girl.getName());
}

@Test
public void test3(){
	Optional<Employee> opt = Optional.of(new Employee("张三", 8888));
	//判断opt中员工对象是否满足条件,如果满足就保留,否则返回空
	Optional<Employee> emp = opt.filter(e -> e.getSalary()>10000);
	System.out.println(emp);
}
@Test
public void test4(){
	Optional<Employee> opt = Optional.of(new Employee("张三", 8888));
	//如果opt中员工对象不为空,就涨薪10%
	Optional<Employee> emp = opt.map(e -> 
	{e.setSalary(e.getSalary()%1.1);return e;});
	System.out.println(emp);
}

@Test
public void test3(){
	Optional<Employee> opt = Optional.of(new Employee("张三", 8888));
	//判断opt中员工对象是否满足条件,如果满足就保留,否则返回空
	Optional<Employee> emp = opt.filter(e -> e.getSalary()>10000);
	System.out.println(emp);
}
@Test
public void test4(){
	Optional<Employee> opt = Optional.of(new Employee("张三", 8888));
	//如果opt中员工对象不为空,就涨薪10%
	Optional<Employee> emp = opt.map(e -> 
	{e.setSalary(e.getSalary()%1.1);return e;});
	System.out.println(emp);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值