本文共 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() {       Supplier        supplier = () -> "测试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() {       Consumer        consumer = (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() {       Predicate        predicate = (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() {       Function        function = (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() {       List        list = new ArrayList         ();    list.add("甲");    list.add("乙");    list.add("丙");    list.add("丁");    list.stream().forEach((item) -> System.out.println(item));}            参数是一个Predicate;
@Testpublic void testFilter() {       List        list = 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"};    List        list = 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/