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

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

Lambda表达式与Stream

文章目录

1. Lambda表达式

1.1 基操

一个接口如果只有一个抽象方法,那么这个接口就是一个函数式接口。我们可以使用@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方法的参数:

  • 参数是一个继承了MyFunctionalInterface的类的对象;
  • 写一个匿名内部类,里面重写MyFunctionalInterface的抽象方法;
  • 使用Lambda表达式简化匿名内部类的写法。
  • 例如:

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

    1.2 方法引用

    如果已经有了现成的方法,有些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 (返回该类的对象数组)
  • 1.3 四种常用的函数式接口

    1.3.1 Supplier

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

    package java.util.function;@FunctionalInterfacepublic interface Supplier
    { T get();}

    测试案例:

    @Testpublic void testSupplier() {    Supplier
    supplier = () -> "测试supplier"; System.out.println(supplier.get());}

    1.3.2 Consumer

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

    package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Consumer
    { void accept(T t); 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);}

    1.3.3 Predicate

    用于判断,返回值为boolean,源码如下:

    package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Predicate
    { boolean test(T t); default Predicate
    and(Predicate
    other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } default Predicate
    or(Predicate
    other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } default Predicate
    negate() { return (t) -> !test(t); } static Predicate
    isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : obj -> targetRef.equals(obj); }}

    测试案例:

    @Testpublic void testPredicate() {    Predicate
    predicate = (str) -> str.length() > 5; System.out.println(predicate.test("ohhhhhhhh"));}

    1.3.4 Function

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

    package java.util.function;import java.util.Objects;@FunctionalInterfacepublic interface Function
    { R apply(T t); default Function
    compose(Function
    before) { Objects.requireNonNull(before); return (T t) -> apply(before.apply(t)); } default Function
    andThen(Function
    after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } 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

    Stream是JavaNME中的核心概念,代表一个可读的、可处理的数据流。Stream可以分为终结操作和非终结操作,非终结操作完成后仍然返回一个流对象,支持链式调用。

    2.1 基操

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

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

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

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

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

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

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

    你可能感兴趣的文章
    Nginx 反向代理配置去除前缀
    查看>>
    nginx 后端获取真实ip
    查看>>
    Nginx 学习总结(17)—— 8 个免费开源 Nginx 管理系统,轻松管理 Nginx 站点配置
    查看>>
    nginx 常用配置记录
    查看>>
    Nginx 我们必须知道的那些事
    查看>>
    Nginx 的 proxy_pass 使用简介
    查看>>
    Nginx 的配置文件中的 keepalive 介绍
    查看>>
    nginx 配置 单页面应用的解决方案
    查看>>
    nginx 配置~~~本身就是一个静态资源的服务器
    查看>>
    Nginx下配置codeigniter框架方法
    查看>>
    nginx添加模块与https支持
    查看>>
    Nginx的Rewrite正则表达式,匹配非某单词
    查看>>
    Nginx的使用总结(一)
    查看>>
    Nginx的是什么?干什么用的?
    查看>>
    Nginx访问控制_登陆权限的控制(http_auth_basic_module)
    查看>>
    nginx负载均衡的五种算法
    查看>>
    Nginx配置ssl实现https
    查看>>
    Nginx配置TCP代理指南
    查看>>
    Nginx配置代理解决本地html进行ajax请求接口跨域问题
    查看>>
    Nginx配置参数中文说明
    查看>>