前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Java的函数式接口以及Lambda表达式

Java的函数式接口以及Lambda表达式

作者头像
半月无霜
发布于 2023-03-03 06:54:10
发布于 2023-03-03 06:54:10
45400
代码可运行
举报
文章被收录于专栏:半月无霜半月无霜
运行总次数:0
代码可运行

Java的函数式接口以及Lambda表达式

一、介绍

java中,大家肯定使用过lambda表达式吧,这是适用于函数式接口的一种便捷写法。

那么什么是函数式接口,简单点来说,一个接口中有且只有一个需要实现的方法,那么这个接口就是函数式接口

如果一个接口,你想定义为函数式接口,建议加上注解@Functionionallnterface,标注这个接口成为函数式接口,用来进行提示。

例如,多线程的Runnable接口就是一个函数式接口,如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.lang;

@FunctionalInterface
public interface Runnable {
    
    public abstract void run();
}

所以,我们在使用多线程时,可以使用lambda表达式进行简化

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.banmoon.test;

import org.junit.jupiter.api.Test;

public class SomethingTest {

    @Test
    public void test() {
        // 匿名内部类写法
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("匿名内部类写法");
            }
        }).start();

        // lambda表达式,小括号是入参,大括号是函数式接口中唯一方法的实现
        new Thread(() -> {
            System.out.println("lambda表达式写法");
        }).start();

        // 方法实现只有单行时,可以再简写,省略大括号
        new Thread(() -> System.out.println("lambda表达式写法")).start();
    }

}

二、常用的函数式接口

1)Function<T, R>

先看源码,发现里面居然有四个方法。又仔细一看,确实里面仅有一个apply方法需要实现,所以Function也是一个函数式接口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }

    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

这个函数式接口,接受有两个泛型,一个作为入参,一个作为出参

我第一时间就想到了转换类型,来看这个,从Integer转换为String,且内部做了一定的处理

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.banmoon.test;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

public class SomethingTest {

    @Test
    public void test() {
        List<Integer> list = new ArrayList<Integer>(){{
            add(7); add(5); add(1); add(2);
            add(8); add(4); add(3); add(6);
            add(3); add(6); add(3); add(6);
        }};

        Function<Integer, String> myFunction = new Function<Integer, String>() {
            @Override
            public String apply(Integer i) {
                return "你好" + i;
            }
        };
        List<String> stringList = list.stream().map(myFunction).collect(Collectors.toList());
        System.out.println(stringList);

		// 使用lambda表达式
        List<String> stringList1 = list.stream().map((i) -> {
            return "你好" + i;
        }).collect(Collectors.toList());

        // 再简写,当参数仅有一个时,小括号可以省略
        stringList1 = list.stream().map(i -> {
            return "你好" + i;
        }).collect(Collectors.toList());
        
        // 再简写,当实现的方法仅有一行语句时,大括号及return可以省略
        stringList1 = list.stream().map(i -> "你好" + i).collect(Collectors.toList());
        System.out.println(stringList1);
    }

}

看下stream接口中的这个map方法,需要我们传入一个Function接口的实现类对象,使用lambda表达式轻松实现对函数式接口的实现类对象的构建

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.util.stream;

public interface Stream<T> extends BaseStream<T, Stream<T>> {
    
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);
}

2)Predicate<T>

先看源码,泛型只需要指定一个,需要实现的方法一个入参,出参是boolean,作用于判断的一个函数式接口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
    
	default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

来查看使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.banmoon.test;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class SomethingTest {

    @Test
    public void test() {
        List<Integer> list = new ArrayList<Integer>(){{
            add(7); add(5); add(1); add(2);
            add(8); add(4); add(3); add(6);
            add(3); add(6); add(3); add(6);
        }};

        Predicate<Integer> myPredicate = new Predicate<Integer>() {
            @Override
            public boolean test(Integer i) {
                return i>5;
            }
        };

        List<Integer> filterList = list.stream().filter(myPredicate).collect(Collectors.toList());
        System.out.println(filterList);

        // lambda表达式简化
        filterList = list.stream().filter(i -> i > 5).collect(Collectors.toList());
        System.out.println(filterList);
    }

}

看下stream接口中的这个filter方法,需要我们传入一个Predicate接口的实现类对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.util.stream;

public interface Stream<T> extends BaseStream<T, Stream<T>> {
    
	Stream<T> filter(Predicate<? super T> predicate);
}

3)Consumer<T>

看类名也能看出来,这是一个消费型的函数式接口,有入参,但没有返回值

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.util.function;

import java.util.Objects;

@FunctionalInterface
public interface Consumer<T> {

    void accept(T t);

    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); after.accept(t); };
    }
}

使用如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.banmoon.test;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;

public class SomethingTest {

    @Test
    public void test() {
        List<Integer> list = new ArrayList<Integer>(){{
            add(7); add(5); add(1); add(2);
            add(8); add(4); add(3); add(6);
            add(3); add(6); add(3); add(6);
        }};

        Consumer myConsumer = new Consumer() {
            @Override
            public void accept(Object o) {
                if(Objects.equals(o, 6))
                    return;
                System.out.print(o);
            }
        };
        list.forEach(myConsumer);

        // lambda表达式简化
        System.out.println("\n========== 分割线 ==========");
        list.forEach(a -> {
            if(Objects.equals(a, 6))
                return;
            System.out.print(a);
        });
    }

}

查看forEach方法的源码,需要我们传入一个Consumer接口的实现类对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

public interface Iterable<T> {

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

}

总有人问,为什么forEach方法不能使用breakcontinue。现在看了源码,你还有这样的疑问吗?

4)Supplier<T>

供给型接口,只有出参,没有入参。在使用上并不多见,先看源码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.util.function;

@FunctionalInterface
public interface Supplier<T> {

    T get();
}

查看使用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.banmoon.test;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;

public class SomethingTest {

    @Test
    public void test() {
        List<User> list = new ArrayList<User>() {{
            add(new User("半月1", 18, 90));
            add(null);
        }};

        Supplier<User> mySupplier = new Supplier() {
            @Override
            public Object get() {
                return new User("未知", 0, 0);
            }
        };
        list.forEach(a -> {
            User user = Optional.ofNullable(a)
                    .orElseGet(mySupplier);
            System.out.println(user);
        });

        System.out.println("========== 分割线 ==========");
        // lambda表达式简化
        list.forEach(a -> {
            User user = Optional.ofNullable(a)
                    .orElseGet(() -> new User("未知", 0, 0));
            System.out.println(user);
        });
    }

}

@Data
@AllArgsConstructor
class User {
    private String name;
    private Integer age;
    private Integer score;
}

查看Optional的源码,这个方法主要作用是,当前对象为null值后,将使用供给的对象

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package java.util;

import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

public final class Optional<T> {

    private final T value;

    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

}

三、最后

上面例举的四个函数式接口,是比较经典的,在很多简化的代码中都可以看到他们的身影。

java8之后,lambda表达式出现,极大地提高了开发的效率,也使得java复杂臃肿的代码得到了缓解。

可谁知道,java8的发布时间在2013年9月份呢,距今都已经有9年的时间了,如果还不了解这上面这些接口,建议先使用Stream流处理。一段时间后,你会明白这些接口的。

使用stream的文章我也有写,可以参考进行学习。

我是半月,祝你幸福!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java中的Lambda表达式与函数式接口详解
在Java 8中,引入了Lambda表达式和函数式接口,这是Java语言中引入的一个重要特性,使得Java编程更加简洁、灵活,支持函数式编程风格。Lambda表达式提供了更简洁的语法来表达匿名方法,而函数式接口则为Lambda表达式提供了基础设施。本文将对Java中的Lambda表达式和函数式接口进行详解,并通过代码示例帮助理解。
一键难忘
2025/02/04
1930
【小家java】java8新特性之---函数式接口(Supplier、Consumer、Predicate、Function、UnaryOperator,通往高阶设计的好工具)
首先,它还是一个接口,所以必须满足接口最基本的定义。但它是一个特殊的接口:SAM类型的接口(Single Abstract Method)。可以在调用时,使用一个lambda表达式作为参数。 定义要求:
YourBatman
2019/09/03
1K0
【小家java】java8新特性之---函数式接口(Supplier、Consumer、Predicate、Function、UnaryOperator,通往高阶设计的好工具)
lambda表达式与函数式编程
lambda表达式是java支持函数式编程的实现方案,很多高级语言已经支持lambda表达式,像python、javascript等。lambda表达式使代码更加简洁,而且在理解了语法之后,可读性也更加好。
搬砖俱乐部
2019/09/25
5920
Java 8 - 03 Lambda 函数式接口Predicate & Consumer & Function & Supplier
Java 8 - 02 Lambda Expression中我们讨论了函数式接口, 函数式接口定义且只定义了一个抽象方法。因为抽象方法的签名可以描述Lambda表达式的签名。函数式接口的抽象方法的签名称为函数描述符。
小小工匠
2021/08/17
6180
浅谈lambda表达式<最通俗易懂的讲解>
lambda体中调用方法的参数列表和返回值类型,要和函数式接口中抽象方法的参数列表和返回值类型保持一致。
Java编程指南
2019/11/05
4960
浅谈lambda表达式<最通俗易懂的讲解>
JDK1.8新特性(四):函数式接口
上一篇JDK1.8新特性(三):Lambda表达式,让你爱不释手,只是简单的讲到Lambda表达式的语法、使用,使得你对它产生了好感,而Lambda表达式是如何实现、定义,你可能不太清楚。本篇将会详细介绍函数式接口,让你在使用JDK新特性时,做到心中有数,自信满满。
xcbeyond
2020/05/31
1K0
JDK1.8新特性(四):函数式接口
[二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口
        比如接收双参数的,有 Bi 前缀, 比如 BiConsumer<T,U>, BiFunction<T,U,R> ;
noteless
2018/09/11
1.8K0
[二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例  如何定义函数式接口
Java学习笔记之函数式接口 Stream流
0x00 概述 本文涉及Java知识点:函数式接口,Stream流。 0x01 函数式接口 1.1 函数式接口概述 概念 有且仅有一个抽象方法的接口 如果检测一个接口是不是函数式接口 @FunctionalInterface 放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败 注意事项 我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算我不写这个注解,只要保证满足函数式接口定义的条件,也照样式函数式接口。但是,建议加上该注解 1
Jetpropelledsnake21
2022/03/07
2920
Java学习笔记之函数式接口 Stream流
Lamda 表达式作用域和内置函数式接口
但是和匿名对象不同的是,这里的变量 num 可以不用声明为 final,该代码同样正确:
happyJared
2019/07/31
5620
函数式接口
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/100187.html原文链接:
全栈程序员站长
2021/05/20
5010
Java 8 函数式接口使用示例及相关新特性
函数式接口(Functional Interface)是Java 8对一类特殊类型的接口的称呼。 函数式接口下共有
chenchenchen
2020/05/26
1.7K0
JDK8中的新特性(Lambda、函数式接口、方法引用、Stream)
<font color=red>Java 8</font> (又称为 JDK 8或JDK1.8) 是 Java 语言开发的一个主要版本。 Java 8 是oracle公司于2014年3月发布,可以看成是自Java 5 以来最具革命性的版本。Java 8为Java语言、编译器、类库、开发工具与JVM带来了大量新特性。
鱼找水需要时间
2023/06/01
8090
JDK8中的新特性(Lambda、函数式接口、方法引用、Stream)
Java最常用的四个函数式接口
Java 8 引入了函数式接口,提供了一种新的方法定义和传递行为的方式。函数式接口是指只包含一个抽象方法的接口。这种接口的实例可以通过 Lambda 表达式、方法引用或构造函数引用来创建,让代码更加简洁和可读性更强。
灬沙师弟
2023/05/18
4160
Java最常用的四个函数式接口
玩转Java8的 Stream 之函数式接口
函数式接口是伴随着Stream的诞生而出现的,Java8Stream 作为函数式编程的一种具体实现,开发者无需关注怎么做,只需知道要做什么,各种操作符配合简洁明了的函数式接口给开发者带来了简单快速处理数据的体验。
搜云库技术团队
2020/06/04
4030
【Java8新特性】还没搞懂函数式接口?赶快过来看看吧!
作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了精准定时调度方案,经受住了生产环境的考验。为使更多童鞋受益,现给出开源框架地址:
冰河
2020/10/29
3250
【Java8新特性】还没搞懂函数式接口?赶快过来看看吧!
函数式接口
所谓的函数式接口,实际上就是接口里面只能有一个抽象方法的接口。Comparator接口就是一个典型的函数式接口,它只有一个抽象方法compare。
HLee
2021/08/15
7150
函数式接口
Lambda表达式
Lambda表达式是可以在函数式接口上使用的。函数式接口就是只定义一个抽象方法的接口。比如:
后端码匠
2019/09/02
5980
java8 最大的特性:Lambda表达式,即函数式编程
java8最大的特性就是引入Lambda表达式,即函数式编程,可以将行为进行传递。总结就是:使用不可变值与函数,函数对不可变值进行处理,映射成另一个值。
二哥聊运营工具
2021/12/17
5100
java8 最大的特性:Lambda表达式,即函数式编程
一文读懂函数式接口、Lambda表达式、Stream
👋 你好,我是 Lorin 洛林,一位 Java 后端技术开发者!座右铭:Technology has the power to make the world a better place.
Lorin 洛林
2024/02/02
5122
一文读懂函数式接口、Lambda表达式、Stream
【Java 8】Lambda 表达式
Lambda(λ) 表达式是一种在 被调用的位置 或者 作为参数传递给函数的位置 定义匿名函数对象 的简便方法。下面是关于 Lambda 表达式的几个点:
零式的天空
2022/03/27
6320
推荐阅读
相关推荐
Java中的Lambda表达式与函数式接口详解
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文