java8 新特性

1、lambda表达式

Lambda 是一个 匿名函数,我们可以把 Lambda 表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。

(1)语法

Lambda 表达式:在Java 8 语言中引入的一种新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda操作符或 箭头操作符。它将 Lambda 分为两个部分:

左侧:指定了 Lambda 表达式需要的参数列表

右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即Lambda 表达式要执行的功能。

语法格式一 : 无参,无返回值

Rannable r1 = () -> {System.out.println("Hello Lanbda !");}

语法格式二: :Lambda 需要一个参数,但是没有返回值。

Cousumer con = (String str) -> {System.out.println("str");}

语法格式三 : 数据类型可以省略 ,因为可由编译器推断得出,称为“类型推断”

Cousumer con = (str) -> {System.out.println("str");}

语法格式四: :Lambda 若只需要一个参数时, 参数的小括号可以省略

Cousumer con = str -> {System.out.println("str");}

语法格式五: :Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值

Comparator com = (x,y) -> { System.out.println("实现函数式接口方法"); return Integer.compare(x,y); }

语法格式六 :当Lambda 体只有一条语句时,return与大括号若有,都可以省略

Comparator com = (x,y) -> Integer.compare(x,y);

(2)类型推断

Lambda表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”。

(3)应用示例
       // 1.创建线程
       new Thread(() -> {
           // method run,do something
       }, "threadName").start();

       // 2.匿名类
        JButton show = new JButton("show");
        show.addActionListener(e -> {
           // method actionPerformed()
        });

       // 3.forEach迭代
        List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
        features.forEach(System.out::println);

        // 4.map 和reduce
        List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500, 600);
        costBeforeTax.stream().map(e -> e + 0.12 * e).forEach(System.out::print);
        double bill = costBeforeTax.stream().map(e -> e + 0.12 * e)
                .reduce((sum, cost) -> sum + cost).get();
        System.out.println(bill);

        // 5.过滤 filter 收集 collect
        List strs = Arrays.asList("abc", "defg", "hi", "jkmln");
        List filtered = strs.stream().filter(e -> e.length() > 2).collect(Collectors.toList());

        // 6.去重
        List nums = Arrays.asList(1 ,2, 3, 1, 4, 5, 2, 6, 8, 7, 6);
        nums = nums.stream().distinct().collect(Collectors.toList());

        // 7.计算最大值、最小值、平均值、总和
        List primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
        IntSummaryStatistics stats = primes.stream().mapToInt(e -> e).summaryStatistics();
        System.out.println("最大值:" +  stats.getMax());
        System.out.println("最小值:" +  stats.getMin());
        System.out.println("平均值:" +  stats.getAverage());
        System.out.println("总和:" +  stats.getSum());
        System.out.println("计数:" +  stats.getCount());
(4)限制

lambda表达式有个限制,只能引用final和final局部变量,也就是说不能再lambda表达式内部修改定义再域外的变量。否则编译报错:

java8 新特性_第1张图片

2、函数式(Functional)接口

只包含一个抽象方法的接口,称为 函数式接口。

Lambda表达式就是一个函数式接口的实例。匿名实现类表示的现在都可以用Lambda表达式来写。

java内置四大核心函数式接口:

java8 新特性_第2张图片

3、方法引用与构造器引用

 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

 方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。

 要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!

 格式:使用操作符 “::” 将类(或对象)与方法名分隔开来。如下三种主要使用情况:

对象::实例方法名

类::静态方法名

类::实例方法

// 方法引用 ClassName::methodName 
如: Comparator com = (x,y) -> Integer.compare(x,y); 
等同于: Comparator com = Integer::compare; 

// 构造器引用 ClassName::new 
如: Function fun = (n) -> new MyClass(n); 
等同于: Function fun = MyClass::new; 

//数组引用 type[] :: new 
如: Function new Integer[n]; 
等同于: Function

4、Stream API

Stream 和 Collection 集合的区别:Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。

①Stream 自己不会存储元素。

②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。

③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

Stream操作的三个步骤:

创建Stream -> 中间操作 -> 终止操作(终端操作)

(1)创建Stream

// 方式1:通过集合 
//Java8 中的 Collection 接口被扩展,提供了两个获取流的方法: 
default Stream stream() : 返回一个顺序流 
default Stream parallelStream() : 返回一个并行流 
例: 
List list = Arrays.asList(1, 2, 3, 4, 5); 
Stream integerStream = list.stream(); 

// 方式2:通过数组 
// Java8 中的 Arrays 的静态方法 stream() 可以获取数组流: 
static  Stream stream(T[] array): 返回一个流 
重载形式,能够处理对应基本类型的数组: 
public static IntStream stream(int[] array) 
public static LongStream stream(long[] array) 
public static DoubleStream stream(double[] array) 
例: IntStream stream = Arrays.stream(new int[]{1, 2, 3, 4, 5}); 

// 方式3:通过Stream的of() 
public static Stream of(T... values) // 接收任意可变参数,返回一个流 
例: Stream stringStream = Stream.of("AA", "BB", "CC"); 

// 方式4: 创建无限流 
>迭代 public static Stream iterate(final T seed, final UnaryOperator f) >
生成 public static Stream generate(Supplier s) 
例: 
// 迭代 
Stream stream = Stream.iterate(0, x -> x + 2); stream.limit(10).forEach(System.out::println); 
// 生成 
Stream stream1 = Stream.generate(Math::random); stream1.limit(10).forEach(System.out::println);

(2)Stream的中间操作

(2.1)筛选与切片

java8 新特性_第3张图片

Person p1 = new Person("tom", 11); 
Person p2 = new Person("jerry", 8); 
Person p3 = new Person("marry", 5); 
Person p4 = new Person("john", 14); 
ArrayList list = new ArrayList<>(); 
list.add(p1); 
list.add(p2); 
list.add(p3); 
list.add(p4); 
// 过滤 
List collect = list.stream() .filter(p -> p.getAge() > 10).collect(Collectors.toList()); 
// 去重 
Person p5 = new Person("john", 14); 
collect = list.stream() .distinct() .collect(Collectors.toList()); 
// 截断 
collect = list.stream() .limit(2) .collect(Collectors.toList()); 
// 跳过元素 
collect = list.stream() .skip(2) .collect(Collectors.toList());

(2.2)映射

java8 新特性_第4张图片

List nameList = list.stream() 
.map(Person::getName) 
.collect(Collectors.toList()); // map()和flatMap类似于集合的add()和addAll(),后者会展开元素

(2.3)排序

java8 新特性_第5张图片

// 自定义比较 
List sortedList = list.stream() .sorted((e1, e2) -> e1.getAge()-e2.getAge()) .collect(Collectors.toList()); 
// 数值的比较方法 
sortedList = list.stream() .sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())) .collect(Collectors.toList()); 
// Comparator的静态比较方法 
sortedList = list.stream() .sorted(Comparator.comparingInt(Person::getAge)) .collect(Collectors.toList());

(3)Stream的终止操作

(3.1)匹配与查找

java8 新特性_第6张图片

boolean allMatch = list.stream().allMatch(e -> e.getAge() > 10); 
Optional first = list.stream().findFirst(); 
list.stream().filter(e -> e.getAge() > 10).count(); 
Optional max = list.stream() .filter(e -> e.getAge() > 10) .max(Comparator.comparingInt(Person::getAge)); 
list.stream().filter(e -> e.getAge() > 10).forEach(System.out::println);

(3.2)归约

java8 新特性_第7张图片

Optional reduce = list.stream() .map(Person::getAge) .reduce((e1, e2) -> e1 + e2);

(3.3)收集

(4)Collectors

java8 新特性_第8张图片

5、Optional类

Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。

Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

创建Optional 类对象的方法:

 Optional.of(T t) : 创建一个 Optional 实例,t必须非空;

 Optional.empty() : 创建一个空的 Optional 实例

 Optional.ofNullable(T t) :t可以为null

判断Optional 容器中是否包含对象:

 boolean isPresent() : 判断是否包含对象

 void ifPresent(Consumer consumer) :如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它。

获取Optional 容器的对象:

 T get(): 如果调用对象包含值,返回该值,否则抛异常

 T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。

 T orElseGet(Supplier other) : :如果有值则将其返回,否则返回由Supplier接口实现提供的对象。

 T orElseThrow(Supplier exceptionSupplier) : :如果有值则将其返

回,否则抛出由Supplier接口实现提供的异常。

//使用Optional类的getGirlName(): 
public String getGirlName2(Boy boy){ 
    Optional boyOptional = Optional.ofNullable(boy); 
    //此时的boy1一定非空 
    Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪丽热巴"))); 
    Girl girl = boy1.getGirl(); 
    Optional girlOptional = Optional.ofNullable(girl); 
    //girl1一定非空 
    Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
    return girl1.getName(); 
}

你可能感兴趣的:(J2SE,Java8,java,java8新特性)