
FunctionalInterface注解
Java 8中专门为函数式接口引入了一个新的注解:@FunctionalInterface 。该注解可用于一个接口的定义上,一旦使用该注解来定义接口,编译器将会强制检查该接口是否确实有且仅有一个抽象方法,否则将会报错。
@FunctionalInterfacepublic interface MyFunction {int add(int a, int b);}
通过lambda表达式使用该接口:
public class Main {public static void main(String[] args) {doing((int a, int b) -> 2 * (a + b) , 1, 2);}public static void doing(MyFunction m, int a, int b) {System.out.println(m.add(a, b));}}
Lambda的延迟执行:
例:在参数l=1时,输出三个字符串相加的结果
传统写法:无论参数l是什么,都会执行字符串相加
public class Main3 {public static void main(String[] args) {String s1 = "hello ";String s2 = "world";String s3 = "!";log(1, s1 + s2 + s3);}private static void log(int l, String s) {if (l == 1) {System.out.println(s);}}}
lambda表达式写法:
public class Main2 {public static void main(String[] args) {String s1 = "hello ";String s2 = "world";String s3 = "!";log(1, () -> s1 + s2 + s3);}private static void log(int l, Log log) {if (l == 1) {System.out.println("执行");System.out.println(log.mylog());}}}@FunctionalInterfacepublic interface Log {String mylog();}
在参数l=1时才会执行三个字符串相加。(用匿名内部类方法也会这样执行)
Lambda作为参数和返回值
常用函数式接口
Supplier接口
抽象方法:get
java.util.function.Supplier<T>
接口仅包含一个无参的方法:T get()
。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
主要用于执行lambda表达式,无法传参,可获取返回值
源码:
@FunctionalInterfacepublic interface Supplier<T> {T get();}
使用样例:
public class Main4 {public static void main(String[] args) {String A = "Hello";String B = "World";Supplier<String> fun = () -> A + B;System.out.println(fun.get());}}
Consumer接口
源码:
@FunctionalInterfacepublic interface Consumer<T> {void accept(T t);default Consumer<T> andThen(Consumer<? super T> after) {//保证after不为null,否则会报错Objects.requireNonNull(after);return (T t) -> { accept(t); after.accept(t); };}}
抽象方法:accept
主要用于传入参数执行lambda表达式,但无返回值
public class Main5 {public static void main(String[] args) {Consumer<String> fun1 = (str) -> System.out.println(str);fun1.accept("aaa");}}
默认方法:andThen
public class Main5 {public static void main(String[] args) {String[] array = {"Xiao WenWen", "Big WenWen", "Middle WenWen"};format(s -> System.out.print("姓" + s.split(" ")[0]), s -> System.out.println("名" + s.split(" ")[1]), array);}private static void format(Consumer<String> c1,Consumer<String> c2,String[] arr){for (String s : arr) {//将参数s传入,先执行c1,再执行c2,可进行链式编程c1.andThen(c2).accept(s);}}}
Predicate接口
判断传入参数是否满足条件,满足返回true,否则为false
源码:
@FunctionalInterfacepublic interface Predicate<T> {boolean test(T t);default Predicate<T> and(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) && other.test(t);}default Predicate<T> negate() {return (t) -> !test(t);}default Predicate<T> or(Predicate<? super T> other) {Objects.requireNonNull(other);return (t) -> test(t) || other.test(t);}static <T> Predicate<T> isEqual(Object targetRef) {return (null == targetRef)? Objects::isNull: object -> targetRef.equals(object);}@SuppressWarnings("unchecked")static <T> Predicate<T> not(Predicate<? super T> target) {Objects.requireNonNull(target);return (Predicate<T>)target.negate();}}
抽象方法:test
判断字符串中有没有字母e
public class Main6 {public static void main(String[] args) {Predicate<String> p = s -> s.contains("e");String[] str = {"hello", "my", "dear", "world"};ArrayList<Boolean> arr = new ArrayList<>();for (String s : str) {boolean b = p.test(s);arr.add(b);}System.out.println(arr);}}
输出:
[true, false, true, true]
默认方法:and
判断字符串中有没有字母e和l
private static void demo2() {Predicate<String> p = s -> s.contains("e");Predicate<String> p1 = s -> s.contains("l");String[] str = {"hello", "my", "dear", "world"};ArrayList<Boolean> arr = new ArrayList<>();for (String s : str) {boolean b = p.and(p1).test(s);arr.add(b);}System.out.println(arr);}
输出:
[true, false, false, false]
默认方法:or
判断字符串中有没有字母e或l
private static void demo3() {Predicate<String> p = s -> s.contains("e");Predicate<String> p1 = s -> s.contains("l");String[] str = {"hello", "my", "dear", "world"};ArrayList<Boolean> arr = new ArrayList<>();for (String s : str) {boolean b = p.or(p1).test(s);arr.add(b);}System.out.println(arr);}
输出:
[true, false, true, true]
默认方法:negate(取反)
判断字符串中有没有字母e,有则返回false
private static void demo4() {Predicate<String> p = s -> s.contains("e");String[] str = {"hello", "my", "dear", "world"};ArrayList<Boolean> arr = new ArrayList<>();for (String s : str) {boolean b = p.negate().test(s);arr.add(b);}System.out.println(arr);}
输出:
[false, true, false, true]
静态方法:not
not用于将原lambda表达时返回值取反
判断字符串中有没有字母e,有则返回false
private static void demo5() {Predicate<String> p1 = s -> s.contains("e");Predicate<String> p = Predicate.not(p1);String[] str = {"hello", "my", "dear", "world"};ArrayList<Boolean> arr = new ArrayList<>();for (String s : str) {boolean b = p.test(s);arr.add(b);}System.out.println(arr);}
输出:
[false, true, false, true]
静态方法:isEqual
isEqual方法用于判断两个参数是否相同
private static void demo6() {System.out.print(Predicate.isEqual("aaaa").test("aaaa")+" ");System.out.print(Predicate.isEqual("aaaa").test("aa1a")+" ");System.out.println(Predicate.isEqual("aaaa").test("aa"+"aa"));}
输出:
true false true
Function接口
@FunctionalInterfacepublic interface Function<T, R> {R apply(T t);default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {Objects.requireNonNull(before);return (V v) -> apply(before.apply(v));}default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {Objects.requireNonNull(after);return (T t) -> after.apply(apply(t));}static <T> Function<T, T> identity() {return t -> t;}}
抽象方法:apply
传入一个值,传出一个值
private static void demo1() {Function<String, Integer> fun = (s) -> {return Integer.parseInt("10");};Integer apply = fun.apply("10");System.out.println(apply);}
输出:
10
默认方法:andThen
先执行fun,再将fun的返回值传入fun1
private static void demo1() {Function<String, Integer> fun = (s) -> {return Integer.parseInt("10")+10;};Function<Integer, Integer> fun2 = (i) -> {return i * 10;};Integer apply = fun.andThen(fun2).apply("10");System.out.println(apply);}
输出:
200
默认方法:compose
private static void demo2() {Function<Integer, Integer> fun = (s) -> {return s + 10;};Function<Integer, Integer> fun2 = (i) -> {return i * 10;};Integer apply1 = fun.compose(fun2).apply(10);System.out.println(apply1);}
输出:
110
Stream流
Stream流遍历集合
private static void demo1() {List<String> l = new ArrayList<>();l.add("hello ");l.add("my ");l.add("dear ");l.add("cute");l.add("world");Predicate<String> p=s -> !s.startsWith("h");Predicate<String> p1=s -> s.length() >= 3;Consumer<String> x= System.out::println;l.stream().filter(p).filter(p1).forEach(x);}
输出:
mydearcuteworld
获取流方法
Collection获取流
调用.stream()方法
private static void demo2() {List<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();Set<String> set = new HashSet<>();Stream<String> stream2 = set.stream();}
Map获取流
map.keySet().stream();map.values().stream();map.entrySet().stream();
private static void demo3() {Map<String, String> map = new HashMap<>();Stream<String> keyStream = map.keySet().stream();Stream<String> valueStream = map.values().stream();Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();}
数组获取流
Stream.of(array);
private static void demo4() {String[] array = {"张无忌", "张翠山", "张三丰", "张一元"};Stream<String> stream = Stream.of(array);}
流常用方法
遍历:forEach
private static void demo5() {List<String> l = new ArrayList<>();l.add("hello ");l.add("my ");l.add("dear ");l.add("cute");l.add("world");Consumer<String> x = System.out::println;l.stream().forEach(x);}
过滤器:filter
private static void demo1() {List<String> l = new ArrayList<>();l.add("hello ");l.add("my ");l.add("dear ");l.add("cute");l.add("world");Predicate<String> p = s -> !s.startsWith("h");Predicate<String> p1 = s -> s.length() >= 3;Consumer<String> x = System.out::println;l.stream().filter(p).filter(p1).forEach(x);}
映射:map
private static void demo6() {Stream<String> original = Stream.of("10", "12", "18");Stream<Integer> result = original.map(str-> Integer.parseInt(str));}
计数:count
private static void demo7() {Stream<String> original = Stream.of("10", "12", "18");long count = original.count();System.out.println(count);}
取前几个:limit
private static void demo8() {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");Stream<String> result = original.limit(2);System.out.println(result);}
跳过前几个:skip
private static void demo9() {Stream<String> original = Stream.of("张无忌", "张三丰", "周芷若");Stream<String> result = original.skip(2);result.forEach(System.out::println);}
组合:concat
private static void demo10() {Stream<String> streamA = Stream.of("张无忌");Stream<String> streamB = Stream.of("张翠山");Stream<String> result = Stream.concat(streamA, streamB);result.forEach(System.out::println);}
方法引用
双冒号::为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。
通过对象名引用成员方法
Calculate:
public class Calculate {int add(int a, int b) {return a+b;}}
MyAdd:
@FunctionalInterfacepublic interface MyAdd {int myadding(int a,int b);}
例:
private static void demo1() {Calculate c=new Calculate();MyAdd ma=c::add;int res = ma.myadding(1, 3);System.out.println(res);//4}
通过类名称引用静态方法
private static void demo2() {MyAdd ma2=Math::max;ma2.myadding(1,2);//2}
通过super引用成员方法
MyFun:
@FunctionalInterfacepublic interface MyFun {void say();}
Father:
public class Father {public void sayHello() {System.out.println("输出父类方法");}}
Son:
public class Son extends Father {@Overridepublic void sayHello() {MyFun mf = super::sayHello;mf.say();System.out.println("输出子类方法");}}private static void demo3() {Son s=new Son();s.sayHello();}
通过this引用成员方法
private void demo4() {MyFun mf = this::sayHello;mf.say();}void sayHello() {System.out.println("hello");}
类的构造器引用
Person:
public class Person {private String name;@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +'}';}public Person(String name) {this.name = name;}}
Builder:
@FunctionalInterfacepublic interface Builder {Person buildPerson(String name);}private static void demo5() {Builder b = Person::new;Person wenwen = b.buildPerson("wenwen");System.out.println(wenwen);}
数组的构造器引用
ArrayBuilder:
@FunctionalInterfacepublic interface ArrayBuilder {int[] buildArray(int length);}
构造数组:
private static void demo6() {ArrayBuilder ab = int[]::new;int[] ints = ab.buildArray(5);System.out.println(Arrays.toString(ints));}




