Java8的新特性体验
Lambda表达式和FunctionalInterface
类似scala和python的lambda表达式终于面世,可以大大简化大量的匿名内部类代码,快速来看一眼。
概述@FunctionalInterface
函数式接口是指一个接口中有且只有一个方法的接口,此时的接口可以 加上一个@FunctionalInterface
来标记这个interface是一个函数是接口。当然也不是强制的,只要一个接口中有且只有一个未实现的抽象方法,就可以当作是一个函数式接口。
FunctionalInterface
可以用:lambda表达式,方法引用,或构造的引用来创建。
加上@FunctionalInterface
只是为了让编译器去检查我们的接口,如果不小心写了第二个抽象方法就会报错,编译不通过。(Object的方法除外,因为已经有默认实现)
同时java8对interface有加强实现,如default
的方法可以在子类中实现。
同时java8还允许有static的实现。
以上两个方式都不是抽象方法,不会影响我们的函数式接口的定义。
如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @FunctionalInterface public interface InterfaceMethod { public void method1 () ; }
使用的时候,假设用上面的方法来做回调:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class BankService { public void doSth (String param, InterfaceMethod callback) { System.out.println("业务方法开始回调。。。。" ); callback.method1(); } } BankService bank = new BankService ();bank.doSth("取款" ,new InterfaceMethod () { @Override public void method1 () { System.out.println("执行完毕取款业务的callback逻辑...." ); } }); bank.doSth("转账" ,()->{System.out.println("执行完毕转账业务的callback逻辑2...." );};);
上面只是一个演示,有点丑陋。另外可以看到我们写了那么一个只有一个方法名的空的接口没啥意思。
如果我们业务有很多很多场景都要回调,没必要每个地方都定义一个空的接口,所以JDK给我们预制了常见的functionalInterface
我们可以看一眼常见的类型:
Lambda表达式
Lambda表达式其实完成了实现接口并且实现接口里的方法 这一功能.
一个 Lambda 表达式可以有零个或多个参数
参数的类型既可以明确声明,也可以根据上下文来推断。例如:(int a)与(a)效果相同
所有参数需包含在圆括号内,参数之间用逗号相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c)
空圆括号代表参数集为空。例如:() -> 42
当只有一个参数,且其类型可推导时,圆括号()可省略。例如:a -> return a*a
Lambda 表达式的主体可包含零条或多条语句
如果 Lambda 表达式的主体只有一条语句,花括号{}可省略。匿名函数的返回类型与该主体表达式一致
如果 Lambda 表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)。匿名函数的返回类型与代码块的返回类型一致,若没有返回则为空
1 2 3 4 5 6 () -> {return 0 ;}, (int i) -> {return 0 ;}, (int i) -> {System.out.println(i)}, (int i, int j) -> {System.out.println(i)}, (int i, int j) -> {return i+j;}, (int i, int j) -> {return i>j;},
如:
1 Runnable o1 = () -> { System.out.println("hi" ); };
函数式接口在包jjava.util.function
包中,主要包括:
Consumer
顾名思义是给我们消费用的,看看他的参数和返回:
他是一个单个参数、无返回 的一个函数式接口,用于我们消费参数并执行一个操作 使用。
也就是: Consumer 一个参数,供消费用的。 void accept(T t);
1 2 3 4 5 6 7 8 9 10 @FunctionalInterface public interface Consumer <T> { void accept (T t) ; }
使用方式如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class BankService { int balance = 0 ; public void recharge (int amt, Consumer<Integer>callback) { balance += amt; callback.accept(balance); } } bank.recharge(100 ,balance->System.out.println("recharge completed,余额是...." +balance));
当然那还有一堆定制更多的Consumer
,如DoubleConsumer
消费Double数据的,IntConsumer
消费Int数据的,BiConsumer
消费两个数据的。
更深入定制的如:ObjIntConsumer
是消费一个Obj,一个Int,他其实是一种BiConsumer
,也就是消费两个对象。
1 2 3 4 5 6 7 8 9 10 11 @FunctionalInterface public interface ObjIntConsumer <T> { void accept (T t, int value) ; }
Function
顾名思义,是一个操作。既然是一个操作就有参数和返回值。所以
1 2 3 4 5 6 7 8 9 10 11 12 13 @FunctionalInterface public interface Function <T, R> { R apply (T t) ; }
应用如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class BankService { public void rechargeAndTax (int amount, Function<Integer, Integer>calculateTax) { amount -= calculateTax.apply(amount); this .balance += amount; } } bank.rechargeAndTax(100 ,amount->amount - 10 );
Function的变种比较多如LongFunction
就是传入一个long,然后进行计算返回一个自定义类型对象:
1 2 3 4 5 @FunctionalInterface public interface LongFunction <R> { R apply (long value) ; }
类似的还有IntFunction
是处理int类型入参的。DoubleFunction
类似。
有个特殊点的,如需要两个参数,一个返回怎么办?答案是BiFunction
,更多参数就没有了,要我们自己实现了。
1 2 3 4 5 6 7 8 9 10 11 12 @FunctionalInterface public interface BiFunction <T, U, R> { R apply (T t, U u) ; }
演示一个简单的双参数的Function使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public boolean cash (int amount, BiFunction<Integer,Integer,Boolean> validation) { if (validation.apply(amount,balance)){ balance -= amount; System.out.println("取现" +amount+"元,余额:" +balance+"元。" ); return true ; }else { System.out.println("校验失败,余额不足!" ); return false ; } } bank.cash(500 , (amount,balance)->balance > amount);
Predicate
可以看作是一个Function<T,Boolean>
,也是进行一个计算,然后返回一个Boolean值而已
1 2 3 4 5 6 7 8 9 10 11 12 13 @FunctionalInterface public interface Predicate <T> { boolean test (T t) ; }
Supplier
没有参数,只是返回,一般用于工厂方法。
1 2 3 4 5 6 7 8 9 10 @FunctionalInterface public interface Supplier <T> { T get () ; }
接口的static和default实现
默认方法的作用:
Java8之前如果已经使用了一个接口,想给这个接口加一个方法,那么需要修改所有实现了这个接口的类 ,是非常恐怖的,而Java8可以允许我们给这个接口新增一个默认实现方法来解决(子类可以override)
当然如果最开始我们的是接口-抽象类-子类
的方式的话,就不用这么麻烦,可以直接在抽象类中新增方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 public interface commonInterface (){ public void method1 () ; default public void method2 () { } public static void method4 () { } }
方法引用::
双冒号代表引用一个方法,通过方法引用来创建函数式接口的实现(引用一个方法来当作一个函数是方法的实现),如:
限制条件:
方法实现只能调用一个方法,一行
引用的那个方法和我们定义的函数式方法的参数和返回值是一致的
引用实例方法
把PrintStream
类的println
方法引用过来当作一个函数是接口:
1 2 3 4 5 6 Consumer<String> consumer = s -> System.out.println(s); consumer.accept("sam" ); Consumer<String> consumer = System.out::println; consumer.accept("sam" );
因为 println的实现就是传入一个String,没有返回值,和我们Consumer<String>
的需求一模一样:
而且我们的需求是只用一行 就能完成业务System.out.println(str),不能再有别的代码,否则就不行。
1 2 3 4 5 6 7 public void println (String x) { synchronized (this ) { print(x); newLine(); } }
同理:
1 2 3 4 5 Arrays.sort(strArrs, (s1,s2)->s1.compareToIgnoreCase(s2)); Comparator<PersonBean> byName = Comparator.comparing(PersonBean::getUserName);
引用静态方法
1 2 3 BiFunction<Integer,Integer,Integer> max = Math::max; int bigger = max(2 ,3 );
引用构造方法
1 2 3 Function<Integer,StringBuffer> sbCreator = StringBuffer::new ; sbCreator.apply(1024 );
引用数组
1 2 3 4 Function<Integer,int []> arrCreator = int []::new ; arrCreator.apply(1024 );
StreamAPI
forEach是一个Consumer<T>
1 studentList.forEach(each -> System.out.print(each.getUserName()));
map是一个Function<? super T, ? extends R>
1 2 3 studentList.stream().map(PersonBean::getAge).distinct().collect(Collectors.toList())
先使用map去处理每一个list的对象,里面使用person.getAge()
返回了Int的年龄,然后使用distinct变成另一个stream,
再collecte的时候引用了另外一个Collectors.toList()
中实现好的方法
filter 过滤
Stream<T> filter(Predicate<? super T> predicate);
还是返回一个stream,后面继续操作
1 2 3 List<String>names = studentList.stream().filter(each->each.getAge()>16 ).sorted(Comparator.comparingInt(each->each.getAge())).map(PersonBean::getUserName).collect(Collectors.toList()); System.out.println("所有>18学生的姓名按照年龄排序:" +names);
sort
Stream<T> sorted(Comparator<? super T> comparator);
也返回一个stream,后面继续操作
看上面例子
reduce:
求汇总
1 2 3 4 5 6 7 8 9 10 11 public void testStream5 () { int sumAge = studentList.stream().map(each->{ if (each.getAge()>16 ){ return each.getAge(); }else { return 0 ; } }).reduce(0 ,Integer::sum); System.out.println("大于16的人的年龄总和:" +sumAge); }
flatMap 展平
1 2 3 4 5 6 7 8 public void testStream6 () { List<List<Integer>> list =Arrays.asList(Arrays.asList(1 ,2 ),Arrays.asList(3 ,4 ,5 ),Arrays.asList(6 ,7 ,8 )); System.out.println("原始list的数据,是三个list:" ); list.stream().forEach(System.out::println); System.out.println("flatMap后,展平合并了:" ); Stream<Integer> integerStream = list.stream().flatMap(Collection::stream); integerStream.forEach(System.out::println); }
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 原始list的数据,是三个list: [1, 2] [3, 4, 5] [6, 7, 8] flatMap后,展平合并了: 1 2 3 4 5 6 7 8 Process finished with exit code 0
groupingBy
1 2 3 4 5 studentList.stream().collect(Collectors.groupingBy(PersonBean::getClassName)).forEach((k,v)->{ System.out.println("k=" +k); System.out.println("v=" +v); });
输出:
1 2 3 4 5 6 7 k=3班 v=[PersonBean(userName=王五, age=17, married=false, addr=null, isStudent=true, className=3班), PersonBean(userName=朱八, age=15, married=false, addr=null, isStudent=true, className=3班)] k=2班 v=[PersonBean(userName=张三, age=16, married=false, addr=null, isStudent=true, className=2班), PersonBean(userName=李四, age=20, married=false, addr=null, isStudent=true, className=2班), PersonBean(userName=赵六, age=16, married=false, addr=null, isStudent=true, className=2班), PersonBean(userName=何七, age=16, married=false, addr=null, isStudent=true, className=2班)] Process finished with exit code 0
skip、limit、count、distinct等等
比较简单,略
Optional 作为一个if else的替代处理null
先看一眼api
1 2 3 4 5 6 7 1 、isPresent() 2 、get(): 3 、orElse(T other) 4 、ifPresent(Consumer<T> block) 5 、orElseThrow(Supplier<? extends X > exceptionSupplier) 6 、orElseGet(Supplier<? extends T > other) 7 、map/flatMap/filter
再看看源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 public final class Optional <T> { private static final java.util.Optional<?> EMPTY = new java .util.Optional<>(); private final T value; private Optional () { this .value = null ; } private Optional (T value) { this .value = Objects.requireNonNull(value); } public static <T> java.util.Optional<T> empty () { @SuppressWarnings("unchecked") java.util.Optional<T> t = (java.util.Optional<T>) EMPTY; return t; } public static <T> java.util.Optional<T> of (T value) { return new java .util.Optional<>(value); } public static <T> java.util.Optional<T> ofNullable (T value) { return value == null ? empty() : of(value); } public T get () { if (value == null ) { throw new NoSuchElementException ("No value present" ); } return value; } public boolean isPresent () { return value != null ; } public T orElse (T other) { return value != null ? value : other; } public void ifPresent (Consumer<? super T> consumer) { if (value != null ) consumer.accept(value); } public java.util.Optional<T> filter (Predicate<? super T> predicate) { Objects.requireNonNull(predicate); if (!isPresent()) return this ; else return predicate.test(value) ? this : empty(); } public <U> java.util.Optional<U> map (Function<? super T, ? extends U> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return java.util.Optional.ofNullable(mapper.apply(value)); } } public <U> java.util.Optional<U> flatMap (Function<? super T, java.util.Optional<U>> mapper) { Objects.requireNonNull(mapper); if (!isPresent()) return empty(); else { return Objects.requireNonNull(mapper.apply(value)); } } public T orElseGet (Supplier<? extends T> other) { return value != null ? value : other.get(); } public <X extends Throwable > T orElseThrow (Supplier<? extends X> exceptionSupplier) throws X { if (value != null ) { return value; } else { throw exceptionSupplier.get(); } } }
最后试试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public static void func1 (String param) { Optional<String> optional1 = Optional.ofNullable(param); System.out.println(optional1.orElse("如果是null降级为此" )); Optional<String> optional3 = Optional.ofNullable(param); System.out.println(optional3.orElseGet(()->{return "123456" .substring(1 );})); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static void func2 (PersonBean person) { Optional<PersonBean> userOp = Optional.ofNullable(person); PersonBean personBean = userOp.orElseGet(PersonBean::new ); Optional<Integer> ageOp = Optional.ofNullable(personBean.getAge()); if (ageOp.isPresent()){ String ageStr = ageOp.map(String::valueOf).get(); }else { } }
Comparable和Comparator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 public static void testComparable () { List<Car> carList = getCarList(); Collections.sort(carList); carList.forEach(System.out::print); } @Data @AllArgsConstructor class Car implements Comparable { private String name; private double price; @Override public int compareTo (Object o) { Car another = (Car)o; return this .price - another.getPrice()>0 ?1 :-1 ; } }
Comparator 比较器,无侵入性,支持自定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 List<User> users = getUserList(); Comparator userComparator = new Comparator <User>() { @Override public int compare (User o1, User o2) { return o1.getAge()-o2.getAge(); } }; Collections.sort(users, userComparator); users.forEach(System.out::print); users = getUserList(); Collections.sort(users, (o1,o2)->o1.getAge()-o2.getAge()); users.forEach(System.out::print); users = getUserList(); Collections.sort(users, Comparator.comparingInt(User::getAge)); users.forEach(System.out::print); @Data @AllArgsConstructor class User { private int age; private String name; }
optional 参考了 https://www.cnblogs.com/qdhxhz/p/12056745.html