java8新特性

函数式接口

只有一个方法的接口(或者说只有一个方法需要实现的接口,java8支持接口有默认实现)

//常见的函数式接口
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

简单使用:

package fun;

import java.util.function.Function;

/**
 * study01
 *
 * @author : xgj
 * @description : de
 * @date : 2020-09-21 15:09
 **/
public class Main {
    public static void main(String[] args) {
        Function<String, Integer> function = new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.valueOf(s);
            }
        };
        System.out.println(function.apply("123"));
    }
}

精简为Lambda表达式

package fun;

import java.util.function.Function;

/**
 * study01
 *
 * @author : xgj
 * @description : de
 * @date : 2020-09-21 15:09
 **/
public class Main {
    public static void main(String[] args) {

        Function<String, Integer> function =(s)->{return Integer.valueOf(s);};
        System.out.println(function.apply("123"));
    }
}

再精简为流式计算

package fun;

import java.util.function.Function;

/**
 * study01
 *
 * @author : xgj
 * @description : de
 * @date : 2020-09-21 15:09
 **/
public class Main {
    public static void main(String[] args) {

        Function<String, Integer> function = Integer::valueOf;
        System.out.println(function.apply("123"));
    }
}

主要的函数式接口:

  1. Function<T,R> 传入一个参数,存在一个返回值。
  2. Predicate< T > 传入一个参数,返回一个布尔值。
  3. Consumer< T > 传入一个参数,没有返回值。
  4. Supplier< R > 没有参数,有一个返回值。

Lambda表达式

Lambda表达式式jdk8的新特性,支持将函数作为参数传递。使用 Lambda 表达式可以使代码变的更加简洁紧凑。但是其实牺牲了部分效率吧,就是需要进行类型推导。免去了使用匿名方法的麻烦(实际上没怎么变,只是将一些工作交给底层去做了),并且给予Java简单但是强大的函数化的编程能力。

public class Java8Tester {
   public static void main(String args[]){
      Java8Tester tester = new Java8Tester();
        
      // 类型声明
      MathOperation addition = (int a, int b) -> a + b;
        
      // 不用类型声明
      MathOperation subtraction = (a, b) -> a - b;
        
      // 大括号中的返回语句
      MathOperation multiplication = (int a, int b) -> { return a * b; };
        
      // 没有大括号及返回语句
      MathOperation division = (int a, int b) -> a / b;
        
      System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
      System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
      System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
      System.out.println("10 / 5 = " + tester.operate(10, 5, division));
        
      // 不用括号
      GreetingService greetService1 = message ->
      System.out.println("Hello " + message);
        
      // 用括号
      GreetingService greetService2 = (message) ->
      System.out.println("Hello " + message);
        
      greetService1.sayMessage("Runoob");
      greetService2.sayMessage("Google");
   }
    
   interface MathOperation {
      int operation(int a, int b);
   }
    
   interface GreetingService {
      void sayMessage(String message);
   }
    
   private int operate(int a, int b, MathOperation mathOperation){
      return mathOperation.operation(a, b);
   }
}

注意点,在匿名内部类中使用域外的局部变量时,需要变量被final修饰,但是Lambda编写代码的时候不用修饰(但是实际上还是需要修饰,只是人家的类型推导帮我们做了这一步)。

Stream流

  • Stream是元素的集合,这点让Stream看起来用些类似Iterator;
  • 可以支持顺序和并行的对原Stream进行汇聚的操作;

简单示例:

package fun;

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

/**
 * study01
 *
 * @author : xgj
 * @description : de
 * @date : 2020-09-21 15:09
 **/
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        System.out.println(list.stream().filter((i) -> i > 5).count());
    }
}

输出元素大于5的个数:

在此我们总结一下使用Stream的基本步骤:

  1. 创建Stream;
  2. 转换Stream,每次转换原有Stream对象不改变,返回一个新的Stream对象(可以有多次转换);
  3. 对Stream进行聚合(Reduce)操作,获取想要的结果;

创建方法:
Stream的静态方法
Collection集合类的默认实现方法.stream() (常用)

常用的转换方法:

  1. distinct: 对于Stream中包含的元素进行去重操作(去重逻辑依赖元素的equals方法),新生成的Stream中没有重复的元素;
package fun;

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

/**
 * study01
 *
 * @author : xgj
 * @description : de
 * @date : 2020-09-21 15:09
 **/
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        Stream<Integer> distinct = list.stream().distinct();
        distinct.forEach(System.out::println);

    }
}


2. filter: 对于Stream中包含的元素使用给定的过滤函数进行过滤操作,新生成的Stream只包含符合条件的元素;

package fun;

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

/**
 * study01
 *
 * @author : xgj
 * @description : de
 * @date : 2020-09-21 15:09
 **/
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        Stream<Integer> integerStream = list.stream().filter((i)-> i > 5);
        integerStream.forEach(System.out::println);

    }
}

  1. map: 对于Stream中包含的元素使用给定的转换函数进行转换操作,新生成的Stream只包含转换生成的元素。这个方法有三个对于原始类型的变种方法,分别是:mapToInt,mapToLong和mapToDouble。这三个方法也比较好理解,比如mapToInt就是把原始Stream转换成一个新的Stream,这个新生成的Stream中的元素都是int类型。之所以会有这样三个变种方法,可以免除自动装箱/拆箱的额外消耗;
package fun;

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

/**
 * study01
 *
 * @author : xgj
 * @description : de
 * @date : 2020-09-21 15:09
 **/
public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        for (int i = 0; i < 10; i++) {
            list.add(i);
        }
        Stream<Integer> intStream = list.stream().map((i)-> i+100);
        intStream.forEach(System.out::println);

    }
}



4. limit: 对一个Stream进行截断操作,获取其前N个元素,如果原Stream中包含的元素个数小于N,那就获取其所有的元素;
5. skip: 返回一个丢弃原Stream的前N个元素后剩下元素组成的新Stream,如果原Stream中包含的元素个数小于N,那么返回空Stream;
等等

链式编程:

将上述流处理运算组合在一起就是一种链式编程,还有像Stringbuffer的append函数。

posted @ 2020-09-21 15:24  大嘤熊  阅读(128)  评论(0编辑  收藏  举报