5. 函数式接口

5.1 概述

只有一个抽象方法的接口我们称之为函数接口。

JDK的函数式接口都加上了 @FunctionalInterface 注解进行标识。但是无论是否加上该注解只要接口中只有一个抽象方法,都是函数式接口。

在Java中,抽象方法是一种没有方法体(实现代码)的方法,只有声明,而没有具体的实现。它用关键字 abstract 进行声明,通常存在于抽象类或接口中。抽象方法的存在是为了让子类或实现类强制性地提供对这个方法的具体实现。

以下是抽象方法的一些特点和规则:

  1. 没有方法体: 抽象方法只有方法声明,没有具体的实现代码。

  2. 关键字 abstract 抽象方法使用 abstract 关键字进行声明。

  3. 存在于抽象类或接口中: 抽象方法通常存在于抽象类或接口中。如果一个类中包含抽象方法,那么该类必须被声明为抽象类。

  4. 强制子类实现: 子类继承抽象类或实现接口时,必须提供抽象方法的具体实现,否则子类也必须声明为抽象类。

下面是一个简单的例子,演示了抽象方法的使用:

abstract class Shape {// 抽象方法,表示计算面积的操作abstract double calculateArea();
}class Circle extends Shape {double radius;Circle(double radius) {this.radius = radius;}// 实现抽象方法@Overridedouble calculateArea() {return Math.PI * radius * radius;}
}class Rectangle extends Shape {double length;double width;Rectangle(double length, double width) {this.length = length;this.width = width;}// 实现抽象方法@Overridedouble calculateArea() {return length * width;}
}public class Main {public static void main(String[] args) {Circle circle = new Circle(5);System.out.println("Circle Area: " + circle.calculateArea());Rectangle rectangle = new Rectangle(4, 6);System.out.println("Rectangle Area: " + rectangle.calculateArea());}
}

在上述例子中,Shape 类是一个抽象类,包含了一个抽象方法 calculateAreaCircleRectangle 类都继承自 Shape 类,并分别实现了 calculateArea 方法。这样,通过抽象方法,我们可以在不同的子类中提供特定的实现,实现多态性。

5.2 常见函数式接口

在Java中,函数式接口是一个只包含一个抽象方法的接口。从Java 8开始,引入了lambda表达式和函数式接口的概念,使得函数式编程变得更加便利。以下是一些常见的函数式接口:

  1. Runnable:

    • 方法签名: void run()
    • 用于表示可以在一个线程中运行的代码块。
  2. Callable:

    • 方法签名: V call() throws Exception
    • Runnable类似,但可以返回一个结果并抛出异常。
  3. Comparator:

    • 方法签名: int compare(T o1, T o2)
    • 用于比较两个对象。常用于排序算法或集合操作。
  4. ActionListener:

    • 方法签名: void actionPerformed(ActionEvent e)
    • 用于处理图形用户界面 (GUI) 中的动作事件。
  5. Callable:

    • 方法签名: V call() throws Exception
    • 用于表示一个可以调用并返回结果或抛出异常的任务。
  6. Supplier:

    • 方法签名: T get()
    • 用于提供一个值。通常在延迟计算中使用,只有在需要时才计算。
  7. Consumer:

    • 方法签名: void accept(T t)
    • 用于接受一个参数并执行某些操作,没有返回值。
  8. Function:

    • 方法签名: R apply(T t)
    • 用于接受一个参数并返回结果。
  9. Predicate:

    • 方法签名: boolean test(T t)
    • 用于测试某个条件是否满足,返回一个布尔值。
  10. BiFunction:

  • 方法签名: R apply(T t, U u)
  • Function类似,但接受两个参数。
  1. UnaryOperator:
  • 方法签名: T apply(T t)
  • 表示一元操作,接受一个参数并返回结果,参数和返回值的类型相同。
  1. BinaryOperator:
  • 方法签名: T apply(T t1, T t2)
  • 表示二元操作,接受两个参数并返回结果,参数和返回值的类型相同。

这些函数式接口在java.util.function包中定义。它们为Lambda表达式提供了一种方便的方式,使得在Java中进行函数式编程变得更加简洁和灵活。

- Consumer 消费接口

根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中对传入的参数进行消费。

Consumer 是 Java 中的一个函数式接口,用于表示接受一个参数并在处理后不返回任何结果的操作。它包含一个名为 accept 的抽象方法,该方法接受一个参数,执行某些操作,但没有返回值。

接口定义如下:

@FunctionalInterface
public interface Consumer<T> {void accept(T t);// 其他默认方法和静态方法省略
}

Consumer 接口的泛型类型 T 表示参数的类型。你可以使用 Consumer 接口来执行各种消费操作,例如打印、修改对象的状态等。

以下是一个简单的例子,演示了如何使用 Consumer 接口:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;public class ConsumerExample {public static void main(String[] args) {// 创建一个列表List<String> names = new ArrayList<>();names.add("Alice");names.add("Bob");names.add("Charlie");// 使用 Consumer 接口打印每个名称Consumer<String> printName = (String name) -> System.out.println(name);// 遍历列表,并对每个元素执行 Consumer 操作names.forEach(printName);}
}

在这个例子中,我们创建了一个 Consumer 对象 printName,它负责打印字符串。然后,我们使用 forEach 方法遍历名字列表,并对每个名字应用 printName 操作。

注意:由于 Consumer 是一个函数式接口,因此可以使用 lambda 表达式来简化匿名类的创建。在上述例子中,(String name) -> System.out.println(name) 就是一个 Consumer 的 lambda 表达式。

- Function 计算转换接口

根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中对传入的参数计算或转换,把结果返回

Function 是 Java 中的一个函数式接口,用于表示接受一个参数并返回结果的操作。它包含一个名为 apply 的抽象方法,该方法接受一个参数并返回计算的结果。

接口定义如下:

@FunctionalInterface
public interface Function<T, R> {R apply(T t);// 其他默认方法和静态方法省略
}

Function 接口的泛型类型 T 表示输入的参数类型,而泛型类型 R 表示返回值的类型。你可以使用 Function 接口来执行各种转换和计算操作。

以下是一个简单的例子,演示了如何使用 Function 接口:

import java.util.function.Function;public class FunctionExample {public static void main(String[] args) {// 创建一个 Function 对象,用于将字符串转换为整数Function<String, Integer> stringToInteger = Integer::parseInt;// 使用 apply 方法进行转换Integer result = stringToInteger.apply("123");System.out.println("Result: " + result); // 输出: Result: 123}
}

在这个例子中,我们创建了一个 Function 对象 stringToInteger,它负责将字符串转换为整数。然后,我们使用 apply 方法将字符串 "123" 应用于 stringToInteger,得到转换后的整数结果。

由于 Function 是一个函数式接口,因此可以使用 lambda 表达式来简化匿名类的创建。在上述例子中,Integer::parseInt 就是一个 Function 的 lambda 表达式。

- Predicate 判断接口

根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中对传入的参数条件判断,返回判断结果

Predicate 是 Java 中的一个函数式接口,用于表示一个断言(判断条件),接受一个参数并返回一个布尔值。它包含一个名为 test 的抽象方法,该方法接受一个参数并返回一个布尔值,表示是否满足某个条件。

接口定义如下:

@FunctionalInterface
public interface Predicate<T> {boolean test(T t);// 其他默认方法和静态方法省略
}

Predicate 接口的泛型类型 T 表示输入的参数类型。你可以使用 Predicate 接口来进行各种条件判断,例如筛选集合元素、过滤数据等。

以下是一个简单的例子,演示了如何使用 Predicate 接口:

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;public class PredicateExample {public static void main(String[] args) {// 创建一个 Predicate 对象,用于判断字符串是否包含字母 "a"Predicate<String> containsA = s -> s.contains("a");// 创建一个字符串列表List<String> words = Arrays.asList("apple", "banana", "orange", "grape");// 使用 Predicate 进行筛选System.out.println("Words containing 'a':");for (String word : words) {if (containsA.test(word)) {System.out.println(word);}}}
}

在这个例子中,我们创建了一个 Predicate 对象 containsA,它负责判断字符串是否包含字母 “a”。然后,我们使用该 Predicate 对象对字符串列表进行筛选,只输出包含字母 “a” 的单词。

由于 Predicate 是一个函数式接口,因此可以使用 lambda 表达式来简化匿名类的创建。在上述例子中,s -> s.contains("a") 就是一个 Predicate 的 lambda 表达式。

- Supplier 生产型接口

根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中创建对象,把创建好的对象返回。

Supplier 是 Java 中的一个函数式接口,用于表示一个生产者,不接受任何参数但返回一个结果。它包含一个名为 get 的抽象方法,该方法不接受任何参数并返回一个结果。

接口定义如下:

@FunctionalInterface
public interface Supplier<T> {T get();// 其他默认方法和静态方法省略
}

Supplier 接口的泛型类型 T 表示返回值的类型。你可以使用 Supplier 接口来生成或提供数据,通常在需要延迟计算或按需生成值的场景中使用。

以下是一个简单的例子,演示了如何使用 Supplier 接口:

import java.util.function.Supplier;public class SupplierExample {public static void main(String[] args) {// 创建一个 Supplier 对象,用于提供随机数Supplier<Integer> randomSupplier = () -> (int) (Math.random() * 100);// 获取并输出随机数int randomNumber = randomSupplier.get();System.out.println("Random Number: " + randomNumber);}
}

在这个例子中,我们创建了一个 Supplier 对象 randomSupplier,它负责生成一个介于 0 到 100 之间的随机整数。然后,我们使用 get 方法获取并输出这个随机数。

由于 Supplier 是一个函数式接口,因此可以使用 lambda 表达式来简化匿名类的创建。在上述例子中,() -> (int) (Math.random() * 100) 就是一个 Supplier 的 lambda 表达式。

5.3 常用的默认方法

and

我们在使用Predicate接口时候可能需要进行判断条件的拼接。而and方法相当于是使用&&来拼接两个判断条件。

例如:

打印作家中年龄大于17并且姓名的长度大于1的作家。

        List<Author> authors = getAuthors();Stream<Author> authorStream = authors.stream();authorStream.filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge()>17;}}.and(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getName().length()>1;}})).forEach(author -> System.out.println(author));

or

我们在使用Predicate接口时候可能需要进行判断条件的拼接。而or方法相当于是使用 || 来拼接两个判断条件。

例如:

打印作家中年龄大于17或者姓名的长度小于2的作家。

//        打印作家中年龄大于17或者姓名的长度小于2的作家。List<Author> authors = getAuthors();authors.stream().filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge()>17;}}.or(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getName().length()<2;}})).forEach(author -> System.out.println(author.getName()));

negate

Predicate接口中的方法。negate方法相当于是在判断添加前面加了个! 表示取反

例如:

打印作家中年龄不大于17的作家。

//        打印作家中年龄不大于17的作家。List<Author> authors = getAuthors();authors.stream().filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge()>17;}}.negate()).forEach(author -> System.out.println(author.getAge()));

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/109695.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AOP系列】6.缓存处理

在Java中&#xff0c;我们可以使用Spring AOP&#xff08;面向切面编程&#xff09;和自定义注解来做缓存处理。以下是一个简单的示例&#xff1a; 首先&#xff0c;我们创建一个自定义注解&#xff0c;用于标记需要进行缓存处理的方法&#xff1a; import java.lang.annotat…

联想G50笔记本直接使用F键功能(F1~F12)需要在BIOS设置关闭热键功能可以这样操作!

如果开启启用热键模式按F1就会出现FnF1的效果&#xff0c;不喜欢此方式按键的用户可以进入BIOS设置界面停用热键模式即可。 停用热键模式方法如下&#xff1a; 1、重新启动笔记本电脑&#xff0c;当笔记本电脑屏幕出现Lenovo标识的时候&#xff0c;立即按FnF2进入BIOS设置界面…

表单规定输入域的选项列表(html5新元素)

datalist datalist 元素规定输入域的选项列表。 datalist属性规定 form 或 input 域应该拥有自动完成功能。当用户在自动完成域中开始输入时&#xff0c;浏览器应该在该域中显示填写的选项&#xff1a; 使用 input元素的列表属性与datalist元素绑定. 还有一定的搜索能力&…

CVE-2020-9483 apache skywalking SQL注入漏洞

漏洞概述 当使用H2 / MySQL / TiDB作为Apache SkyWalking存储时&#xff0c;通过GraphQL协议查询元数据时&#xff0c;存在SQL注入漏洞&#xff0c;该漏洞允许访问未指定的数据。 Apache SkyWalking 6.0.0到6.6.0、7.0.0 H2 / MySQL / TiDB存储实现不使用适当的方法来设置SQL参…

GPIO基本原理

名词解释 高低电平&#xff1a;GPIO引脚电平范围&#xff1a;0V~3.3V&#xff08;部分引脚可容忍5V&#xff09;数据0就是0V&#xff0c;代表低电平&#xff1b;数据1就是3.3V&#xff0c;代表高电平&#xff1b; STM32是32位的单片机&#xff0c;所以内部寄存器也都是32位的…

FilterRegistrationBean能不能排除指定url

文章目录 什么是FilterRegistrationBean举个栗子但是如果我想要排除某些uri方法总结FilterRegistrationBean只能设置指定的url进行过滤,而不能指定排除uri,只能使用OncePerRequestFilter的shouldNotFilter方法,排除uri 什么是FilterRegistrationBean FilterRegistrationBean是…

用于细胞定位的指数距离变换图--Exponential Distance Transform Maps for Cell Localization

论文&#xff1a;Exponential Distance Transform Maps for Cell Localization Paper Link&#xff1a; Exponential Distance Transform Maps for Cell Localization Code&#xff08;有EDT Map的生成方式&#xff09;&#xff1a; https://github.com/Boli-trainee/MHFAN 核…

深入了解Golang:基本语法与核心特性解析

1. 引言 Golang&#xff08;Go&#xff09;是谷歌开发的一门开源编程语言&#xff0c;于2007年首次公开亮相&#xff0c;随后在2012年正式发布。Golang以其简洁、高效和可靠的设计而备受开发者青睐。作为一门编译型语言&#xff0c;Golang具有静态类型和垃圾回收功能&#xff…

网络编程 - TCP协议

一&#xff0c;TCP基本概念 TCP的特性&#xff1a; TCP是有连接的&#xff1a;TCP想要通信&#xff0c;就需要先建立连接&#xff0c;之后才能通信 TCP是可靠传输&#xff1a;网络上进行通信&#xff0c;A给B发消息&#xff0c;这个消息是不可能做到100%送达的&#xff0c;所以…

树模型(三)决策树

决策树是什么&#xff1f;决策树(decision tree)是一种基本的分类与回归方法。 长方形代表判断模块 (decision block)&#xff0c;椭圆形成代表终止模块(terminating block)&#xff0c;表示已经得出结论&#xff0c;可以终止运行。从判断模块引出的左右箭头称作为分支(branch)…

【大数据 - Doris 实践】数据表的基本使用(三):数据模型

数据表的基本使用&#xff08;三&#xff09;&#xff1a;数据模型 1.Aggregate 模型1.1 例一&#xff1a;导入数据聚合1.2 例二&#xff1a;保留明细数据1.3 例三&#xff1a;导入数据与已有数据聚合 2.Uniq 模型3.Duplicate 模型4.数据模型的选择建议5.聚合模型的局限性 Dori…

【AI视野·今日CV 计算机视觉论文速览 第268期】Mon, 16 Oct 2023

AI视野今日CS.CV 计算机视觉论文速览 Mon, 16 Oct 2023 Totally 61 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computer Vision Papers Vision-by-Language for Training-Free Compositional Image Retrieval Authors Shyamgopal Karthik, Karsten Roth, Massi…

OpenCV11-图像的模版匹配

OpenCV11-图像的模版匹配 图像的模版匹配 图像的模版匹配 前面通过图像直方图反向投影的方式在图像中寻找模版图像&#xff0c;由于直方图不能直接反映图像的纹理&#xff0c;因此&#xff0c;如果两幅不同的模版图像具有相同的直方图分布特性&#xff0c;那么在同一幅图中对着…

react-redux的connect函数实现

react-redux对store订阅的实现原理&#xff1a; storeContext.js import { createContext } from "react";export const StoreContext createContext() connect.js import React, { PureComponent } from react // import store from ../../store; import {Stor…

ESP RainMaker 客户案例 #2|PitPat

PitPat 是美国领先的健身品牌&#xff0c;致力于通过游戏化的方式改变人们的锻炼习惯&#xff0c;增强健康。该品牌通过智能设备和相关的移动应用程序为从事家庭锻炼的个人提供虚拟跑步体验。目前&#xff0c;PitPat 针对不同受众群体&#xff0c;开发了Superun&#xff0c;Dee…

程序开发中表示密码时使用 password 还是 passcode?

password 和 passcode 是两个经常在计算机和网络安全中使用的术语&#xff0c;两者都是用于身份验证的机制&#xff0c;但它们之间还是存在一些区别的。 password password 通常是指用户自己设置的一串字符&#xff0c;用于保护自己的账户安全。密码通常是静态的&#xff0c;…

druid的简单使用

文章目录 1.数据准备2.pom.xml文件中引用druid3. 在resource目录下创建druid.properties配置文件4. 编写java代码参考文献 1.数据准备 drop table if exists account; create table if not exists account (id int primary key auto_increment,name varchar(10),money dou…

android 13.0 SystemUI导航栏添加虚拟按键功能(三)

1.概述 在13.0的系统产品开发中,对于在SystemUI的原生系统中默认只有三键导航,想添加其他虚拟按键就需要先在构建导航栏的相关布局 中分析结构,然后添加相关的图标xml就可以了,然后添加对应的点击事件,就可以了,接下来先分析第三步关于导航栏的相关布局情况 然后实现虚拟…

从入门到进阶 之 ElasticSearch 文档、分词器 进阶篇

&#x1f339; 以上分享 ElasticSearch 文档、分词器 进阶篇&#xff0c;如有问题请指教写。&#x1f339;&#x1f339; 如你对技术也感兴趣&#xff0c;欢迎交流。&#x1f339;&#x1f339;&#x1f339; 如有需要&#xff0c;请&#x1f44d;点赞&#x1f496;收藏&#…

国际站阿里云服务器无法安装程序怎么办?

阿里云服务器是阿里云推出的一种云核算产品&#xff0c;它能够帮助企业和个人快速建立、扩展和管理网络服务。可是&#xff0c;有时候在运用阿里云服务器时&#xff0c;或许会遇到无法装置程序的问题。本文将具体介绍如何处理这个问题。 阿里云服务器无法装置程序或许是由多种原…