本文共 12019 字,大约阅读时间需要 40 分钟。
首先清楚一个概念,如果一个接口里面只有一个抽象方法,那么这个接口就是一个函数式接口。
我们可以使用@FunctionalInterface
修饰这个接口,被这个注解修饰的接口如果有多个抽象方法,那么编译是不会通过的。
例如:
package com.lambda;@FunctionalInterfacepublic interface MyFunctionalInterface { void method();}
假设Demo类中的show方法如下:
package com.lambda;public class Demo { public static void show(MyFunctionalInterface mfi) { mfi.method(); }}
我们有三种写法传递show方法的参数:
package com.test;import org.junit.Test;import com.lambda.Demo;import com.lambda.MyFunctionalInterface;public class TestDemo { @Test public void testLambda() { // 方法1 // Demo.show(new MyFunctionalInterfaceImpl()); // 方法2 Demo.show(new MyFunctionalInterface() { @Override public void method() { System.out.println("这是匿名内部类的写法"); } }); // 方法3 Demo.show(() -> System.out.println("lambda方式的写法")); }}
这里举两个例子来感受lambda的简洁:
@Testpublic void testThread() { //匿名内部类的写法 new Thread(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread().getName()); } }).start(); //Lambda写法 new Thread(()->System.out.println(Thread.currentThread().getName())).start();}@Testpublic void testComparator() { String[] strs = { "asdfadf","asdfasdfasdf","fasdf","sdfghdsfghshsdfhsdfg"}; //匿名内部类写法 Arrays.sort(strs,new Comparator() { @Override public int compare(String o1, String o2) { return o2.length() - o1.length(); } }); System.out.println(Arrays.toString(strs)); //Lambda的写法 Arrays.sort(strs,(s1,s2)->s1.length()-s2.length()); System.out.println(Arrays.toString(strs));}
如果已经有了现成的方法,有些Lambda表达式是不必要写的,这时候我们就可以把lambda表达式换为方法引用。
举个例子就知道了。
有如下函数式接口:
package com.lambda;@FunctionalInterfacepublic interface Printer { void print(String str);}
有如下方法:
private void p(String s,Printer printer) { printer.print(s);}
方法引用:
@Testpublic void testFFYY() { p("测试lambda表达式", (s) -> System.out.println(s)); p("测试方法引用", System.out::println);}
第一行是使用lambda表达式的方法,但是由于lambda的效果和System.out.println()一样,我们可以直接使用方法引用。
常见的方法引用有以下几种:
用于生产一个指定类型的数据,源码如下:
package java.util.function;@FunctionalInterfacepublic interface Supplier{ /** * Gets a result. * * @return a result */ T get();}
测试案例:
@Testpublic void testSupplier() { Suppliersupplier = () -> "测试supplier"; System.out.println(supplier.get());}
用于消费一个指定类型的数据,源码如下:
package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Consumer{ /** * Performs this operation on the given argument. * * @param t the input argument */ void accept(T t); /** * Returns a composed {@code Consumer} that performs, in sequence, this * operation followed by the {@code after} operation. If performing either * operation throws an exception, it is relayed to the caller of the * composed operation. If performing this operation throws an exception, * the {@code after} operation will not be performed. * * @param after the operation to perform after this operation * @return a composed {@code Consumer} that performs in sequence this * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ default Consumer andThen(Consumer after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; }}
测试案例:
@Testpublic void testConsumer() { Consumerconsumer = (str) -> System.out.println(str); consumer.accept("测试consumer"); consumerAndThen("test andThen in Consumer", str -> System.out.println(str.toUpperCase()), str -> System.out.println(str.toLowerCase()));}private void consumerAndThen(String str,Consumer c1,Consumer c2) { c1.andThen(c2).accept(str);}
用于判断,返回值为boolean,源码如下:
package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Predicate{ /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); /** * Returns a composed predicate that represents a short-circuiting logical * AND of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code false}, then the {@code other} * predicate is not evaluated. * * Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ANDed with this * predicate * @return a composed predicate that represents the short-circuiting logical * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate
and(Predicate other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } /** * Returns a predicate that represents the logical negation of this * predicate. * * @return a predicate that represents the logical negation of this * predicate */ default Predicate negate() { return (t) -> !test(t); } /** * Returns a composed predicate that represents a short-circuiting logical * OR of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code true}, then the {@code other} * predicate is not evaluated. * * Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ORed with this * predicate * @return a composed predicate that represents the short-circuiting logical * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate
or(Predicate other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } /** * Returns a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)}. * * @param the type of arguments to the predicate * @param targetRef the object reference with which to compare for equality, * which may be {@code null} * @return a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)} */ static Predicate isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }}
测试案例:
@Testpublic void testPredicate() { Predicatepredicate = (str) -> str.length() > 5; System.out.println(predicate.test("ohhhhhhhh")); //还有一些与或非的写法,不想写了,感觉没啥必要}
用于将一种数据类型转换为另一种数据类型,源码如下:
package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Function{ /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); /** * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(Function) */ default Function compose(Function before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * * @see #compose(Function) */ default Function andThen(Function after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } /** * Returns a function that always returns its input argument. * * @param the type of the input and output objects to the function * @return a function that always returns its input argument */ static Function identity() { return t -> t; }}
测试案例:
@Testpublic void testFunction() { Functionfunction = (str) -> Integer.valueOf(str) + 10; System.out.println(function.apply("23")); Function function2 = (i) -> String.valueOf(i - 20); String str = function.andThen(function2).apply("78"); System.out.println(str);}
可分为终结操作和非终结操作,非终结操作完成后仍然返回一个流对象,支持链式调用。
终结操作主要有foreach和count。
参数是一个Consumer;
@Testpublic void testForEach() { Listlist = new ArrayList (); list.add("甲"); list.add("乙"); list.add("丙"); list.add("丁"); list.stream().forEach((item) -> System.out.println(item));}
参数是一个Predicate;
@Testpublic void testFilter() { Listlist = new ArrayList (); list.add("aaa"); list.add("asdf"); list.add("dfsh"); list.add("asdfasd"); list.stream().filter(item -> item.length() < 5) .filter(item -> item.startsWith("a")) .forEach(item -> System.out.println(item));}
参数是一个Function;
@Testpublic void testMap() { String[] arr = { "17","234","567","16","23","34","345"}; Stream.of(arr).map(item -> Integer.valueOf(item)) .filter(item -> item > 40) .forEach(item -> System.out.println(item));}
统计个数;
@Testpublic void testCount() { String[] arr = { "17","234","567","16","23","34","345"}; long count = Stream.of(arr).map(item -> Integer.valueOf(item)) .filter(item -> item > 40) .count(); System.out.println(count);}
取流中前n个对象,参数为n;
@Testpublic void testLimit() { String[] arr = { "17","234","567","16","23","34","345"}; Stream.of(arr).limit(4).forEach(item -> System.out.println(item));}
跳过流中前n个对象,参数为n;
@Testpublic void testSkip() { String[] arr = { "17","234","567","16","23","34","345"}; Stream.of(arr).skip(4).forEach(item -> System.out.println(item));}
将两个流合并成一个流,参数为两个流;
@Testpublic void testConcat() { String[] arr = { "17","234","567","16","23","34","345"}; Listlist = new ArrayList (); list.add("aaa"); list.add("asdf"); list.add("dfsh"); list.add("asdfasd"); Stream.concat(Stream.of(arr), list.stream()).forEach(item -> System.out.println(item));}
转载地址:http://dkee.baihongyu.com/