博客
关于我
Java8新特性——从Lambda表达式到Stream流
阅读量:351 次
发布时间:2019-03-04

本文共 12019 字,大约阅读时间需要 40 分钟。

Lambda表达式与Stream

文章目录

Lambda表达式

基操

首先清楚一个概念,如果一个接口里面只有一个抽象方法,那么这个接口就是一个函数式接口。

我们可以使用@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方法的参数:

  1. 参数是一个继承了MyFunctionalInterface的类的对象;
  2. 写一个匿名内部类,里面重写MyFunctionalInterface的抽象方法;
  3. 使用Lambda表达式简化匿名内部类的写法;
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()一样,我们可以直接使用方法引用。

常见的方法引用有以下几种:

  • 对象名::成员方法
  • 类名::静态方法
  • this::成员方法
  • super::成员方法
  • 类名::new (返回该类的对象)
  • 类名[]::new (返回该类的对象数组)

四种常用的函数式接口

Supplier

用于生产一个指定类型的数据,源码如下:

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());}

Consumer

用于消费一个指定类型的数据,源码如下:

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);}

Predicate

用于判断,返回值为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")); //还有一些与或非的写法,不想写了,感觉没啥必要}

Function

用于将一种数据类型转换为另一种数据类型,源码如下:

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);}

Stream

可分为终结操作和非终结操作,非终结操作完成后仍然返回一个流对象,支持链式调用。

终结操作主要有foreach和count。

基操

foreach

参数是一个Consumer;

@Testpublic void testForEach() {       List
list = new ArrayList
(); list.add("甲"); list.add("乙"); list.add("丙"); list.add("丁"); list.stream().forEach((item) -> System.out.println(item));}

filter

参数是一个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));}

map

参数是一个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));}

count

统计个数;

@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);}

limit

取流中前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));}

skip

跳过流中前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));}

concat

将两个流合并成一个流,参数为两个流;

@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/

你可能感兴趣的文章
【Java基础】什么是面向对象?
查看>>
mysql 查询,正数降序排序,负数升序排序
查看>>
MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)...
查看>>
mysql 死锁 Deadlock found when trying to get lock; try restarting transaction
查看>>
mysql 死锁(先delete 后insert)日志分析
查看>>
MySQL 死锁了,怎么办?
查看>>
MySQL 深度分页性能急剧下降,该如何优化?
查看>>
MySQL 深度分页性能急剧下降,该如何优化?
查看>>
MySQL 添加列,修改列,删除列
查看>>
mysql 添加索引
查看>>
MySQL 添加索引,删除索引及其用法
查看>>
mysql 状态检查,备份,修复
查看>>
MySQL 用 limit 为什么会影响性能?
查看>>
MySQL 用 limit 为什么会影响性能?有什么优化方案?
查看>>
MySQL 用户权限管理:授权、撤销、密码更新和用户删除(图文解析)
查看>>
mysql 用户管理和权限设置
查看>>
MySQL 的 varchar 水真的太深了!
查看>>
mysql 的GROUP_CONCAT函数的使用(group_by 如何显示分组之前的数据)
查看>>
MySQL 的instr函数
查看>>
MySQL 的mysql_secure_installation安全脚本执行过程介绍
查看>>