Java8新特性

1.Lambda表达式

java8的新特性之一,Lambda 表达式,也可称为闭包。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

使用 Lambda 表达式可以使代码变的更加简洁紧凑。但是实质上是类似于“语法糖”,将你包装好的代码有编译器来完成转换,从而使代码更加的简洁,不太推荐经常使用,因为它尽管很简洁,但是难懂,难以调试

语法

lambda 表达式的语法格式如下:

(parameters) -> expression
(parameters) ->{ statements; }

Lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

以下通过一个示例来了解具体用法:

public class Lambda {
    public static void main(String[] args) {
        Lambda lambda = new Lambda();
        MathOperation add = (x, y) -> x + y;
        MathOperation sub = (x, y) -> x - y;
        MathOperation multi = (x, y) -> x * y;
        MathOperation div = (x, y) -> x / y;

        System.out.println("加法操作:"+lambda.operate(10, 5, add));
        System.out.println("减法操作:"+lambda.operate(10, 5, sub));
        System.out.println("乘法操作:"+lambda.operate(10, 5, multi));
        System.out.println("除法操作:"+lambda.operate(10, 5, div));
    }
    interface MathOperation{
        int operation(int a, int b);
    }

    private int operate(int a, int b, MathOperation mathoperation){
        return mathoperation.operation(a, b);
    }
}

输出如下:

加法操作:15
减法操作:5
乘法操作:50
除法操作:2

定义另一个MathOperation接口来实现加减乘除,operation实现接口内的方法。
MathOperation add = (x, y) -> x + y;语句的本质就是:

int add(int a, inb b){
	return a + b;
}

MathOperation add用来接收其返回值。

变量作用域

lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。

2.方法引用

方法引用和方法的Lambda表达式一样,只不过是操作符不同而已,方法引用使用一对冒号 ::
以下是示例:
Person.java文件

import java.time.LocalDate;

public class Person {
    LocalDate birthday;

    public static int compareByAge(Person a,Person b){
        return a.birthday.compareTo(b.birthday);
    }

}

Main.java文件:

import java.time.LocalDate;
import java.util.Arrays;
import java.util.Comparator;

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello World!");
        Person[] peoples = new Person[3];
        peoples[0] = new Person();
        peoples[1] = new Person();
        peoples[2] = new Person();

        peoples[0].birthday = LocalDate.of(2019,5,14);
        peoples[1].birthday = LocalDate.parse("2019-04-25");
        peoples[2].birthday = LocalDate.parse("2019-04-16");

        //使用匿名内部类
        Arrays.sort(peoples, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.birthday.compareTo(o2.birthday);
            }
        });

        //使用Lambda表达式
        Arrays.sort(peoples, (o1, o2) -> o1.birthday.compareTo(o2.birthday));

        //使用Lambda表达式和类的静态方法
        Arrays.sort(peoples, ((o1, o2) -> Person.compareByAge(o1, o2)));

        //使用方法引用(引用类的静态方法
        Arrays.sort(peoples, Person::compareByAge);

        for (Person p:peoples){
            System.out.print(p.birthday+"\t");
        }
    }

}

在Main.java中 使用了4钟不同的方法来对peoples中的每个person根据日期来排序

3.函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
例如自定义的函数式接口:

public class test {
    //通过注解@FunctionalInterface来声明一个函数式接口
    @FunctionalInterface
    interface GreetingService
    {
    	//只能有一个抽象方法
    	//但是equals式父类的非抽象方法
    	boolean equals(Object object);
        void sayMessage(String message);
        //也可以定义默认的实现方法
        default void example(){
        }
    }

    public static void main(String[] args){
        //可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):
        GreetingService greetService = message -> System.out.println("Hello " + message);
        greetService.sayMessage("world");
    }
}

以下是已有的函数式接口:

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.security.PrivilegedAction
  • java.util.Comparator
  • java.io.FileFilter
  • java.nio.file.PathMatcher
  • java.lang.reflect.InvocationHandler
  • java.beans.PropertyChangeListener
  • java.awt.event.ActionListener
  • javax.swing.event.ChangeListener
  • java.util.function(java1.8新增)

以function里的Predicate 接口(接受一个输入参数 T,返回一个布尔值结果)为示例:
Predicate源码中提供了5个方法

  • boolean test(T t);
  • default Predicate and(Predicate<? super T> other)
  • default Predicate negate()
  • default Predicate or (Predicate<? super T> other)
  • static Predicate isEqual (Object targetRef)

以下对test(T t)方法进行使用

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

public class Function_interface{

    public static void main(String args[]){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

        // Predicate<Integer> predicate = n -> true
        // n 是一个参数传递到 Predicate 接口的 test 方法
        // n 如果存在则 test 方法返回 true

        System.out.println("输出所有数据:");

        // 传递参数 n
        eval(list, n->true);
        System.out.println();


        // Predicate<Integer> predicate1 = n -> n%2 == 0
        // n 是一个参数传递到 Predicate 接口的 test 方法
        // 如果 n%2 为 0 test 方法返回 true

        System.out.println("输出所有偶数:");
        eval(list, n-> n%2 == 0 );
        System.out.println();
        
        System.out.println("输出大于 3 的所有数字:");
        //详细的调用过程
        eval(list, new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                if(integer > 3){
                    return true;
                }else {
                    return false;
                }
            }
        });
        System.out.println();

    }

    public static void eval(List<Integer> list, Predicate<Integer> predicate) {
        for(Integer i: list) {

            if(predicate.test(i)) {
                System.out.print(i + "\t");
            }
        }
    }
}

输出如下:

输出所有数据:
1 2 3 4 5 6 7 8 9
输出所有偶数:
2 4 6 8
输出大于 3 的所有数字:
4 5 6 7 8 9

4.默认方法

在函数式接口中已经体现,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。
我们只需在方法名前面加个 default 关键字即可实现默认方法。
如自定义的函数式接口中,default便是默认方法

    @FunctionalInterface
    interface GreetingService
    {
    	//只能有一个抽象方法
    	//但是equals式父类的非抽象方法
    	boolean equals(Object object);
        void sayMessage(String message);
        //也可以定义默认的实现方法
        default void example(){
        }
    }

5.Stream

Stream:(流)是一个来自数据源的元素队列并支持聚合操作
该Api中涉及的方法过多,所以通过示例来了解部分方法的使用

import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

public class Stream {
    public static void main(String args[]){
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        System.out.println("列表: " +strings);

        //构造stream,然后返回相匹配的stream,再计算stream元素数目
        long count = strings.stream().filter(String::isEmpty).count();
        System.out.println("空字符串数量为: " + count);

        count = strings.stream().filter(string -> string.length() == 3).count();
        System.out.println("字符串长度为 3 的数量为: " + count);

        //filter返回筛选不为空元素后的stream
        List<String> filtered = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.toList());
        System.out.println("筛选后的列表: " + filtered);

        String mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", "));
        System.out.println("合并字符串: " + mergedString);

        //map方法返回映射后的值
        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        List<Integer> squaresList = numbers.stream().map( i ->i*i).distinct().collect(Collectors.toList());
        System.out.println("Squares List: " + squaresList);


        List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
        System.out.println("列表: " +integers);
        //此处mapToint返回Interger类型的stream
        //IntSummaryStatistics用于收集统计数据(如计数,最小值,最大值,总和和平均值)的状态对象。
        //summaryStatistics()将stream转换为IntSummaryStatistics
        IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics();

        System.out.println("列表中最大的数 : " + stats.getMax());
        System.out.println("列表中最小的数 : " + stats.getMin());
        System.out.println("所有数之和 : " + stats.getSum());
        System.out.println("平均数 : " + stats.getAverage());
        System.out.println("随机数: ");

        Random random = new Random();
        random.ints().limit(10).sorted().forEach(System.out::println);

        // 并行处理
        count = strings.parallelStream().filter(String::isEmpty).count();
        System.out.println("空字符串的数量为: " + count);
    }
}

对于Stream中

  • filter()

Stream filter(Predicate<? super T> predicate);
使用到了Predicate该函数接口,因而可用boolean判断(见函数式接口)

  • collect()

<R, A> R collect(Collector<? super T, A, R> collector);
用于实现归约操作,可用于集合的转换返回列表,collect(Collectors.toList())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值