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

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

Lambda表达式与Stream

文章目录

1. Lambda表达式

1.1 基操

一个接口如果只有一个抽象方法,那么这个接口就是一个函数式接口。我们可以使用@FunctionalInterface修饰这个接口,被这个注解修饰的接口如果有多个抽象方法,那么编译是不会通过的。

例如:

package com.lambda;
@FunctionalInterface
public interface MyFunctionalInterface {
void method();
}

假设Demo类中的show方法如下:

package com.lambda;
public class Demo {
public static void show(MyFunctionalInterface mfi) {
mfi.method();
}
}

我们有三种写法传递show方法的参数:

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

    @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的简洁:

    @Test
    public 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();
    }
    @Test
    public 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;
    @FunctionalInterface
    public interface Printer {
    void print(String str);
    }

    有如下方法:

    private void p(String s, Printer printer) {
    printer.print(s);
    }

    方法引用:

    @Test
    public 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;
    @FunctionalInterface
    public interface Supplier
    {
    T get();
    }

    测试案例:

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

    1.3.2 Consumer

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

    package java.util.function;
    import java.util.Objects;
    @FunctionalInterface
    public interface Consumer
    {
    void accept(T t);
    default Consumer
    andThen(Consumer
    after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
    }
    }

    测试案例:

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

    测试案例:

    @Test
    public 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;
    @FunctionalInterface
    public 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;
    }
    }

    测试案例:

    @Test
    public 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;

    例如:

    @Test
    public 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;

    例如:

    @Test
    public 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;

    例如:

    @Test
    public 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

    统计个数;

    例如:

    @Test
    public 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;

    例如:

    @Test
    public 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;

    例如:

    @Test
    public 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

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

    例如:

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

    你可能感兴趣的文章
    No module named cv2
    查看>>
    No module named tensorboard.main在安装tensorboardX的时候遇到的问题
    查看>>
    No module named ‘MySQLdb‘错误解决No module named ‘MySQLdb‘错误解决
    查看>>
    No new migrations found. Your system is up-to-date.
    查看>>
    No qualifying bean of type XXX found for dependency XXX.
    查看>>
    No resource identifier found for attribute 'srcCompat' in package的解决办法
    查看>>
    No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android
    查看>>
    NO.23 ZenTaoPHP目录结构
    查看>>
    NoClassDefFoundError: org/springframework/boot/context/properties/ConfigurationBeanFactoryMetadata
    查看>>
    Node JS: < 一> 初识Node JS
    查看>>
    Node-RED中使用JSON数据建立web网站
    查看>>
    Node-RED中使用node-red-browser-utils节点实现选择Windows操作系统中的文件并实现图片预览
    查看>>
    Node-RED中使用Notification元件显示警告讯息框(温度过高提示)
    查看>>
    Node-RED中实现HTML表单提交和获取提交的内容
    查看>>
    Node.js 实现类似于.php,.jsp的服务器页面技术,自动路由
    查看>>
    node.js 怎么新建一个站点端口
    查看>>
    Node.js 文件系统的各种用法和常见场景
    查看>>
    node.js 配置首页打开页面
    查看>>
    node.js+react写的一个登录注册 demo测试
    查看>>
    Node.js中环境变量process.env详解
    查看>>