Lambda表达式

Java8引入Lambda表达式,可以使代码更简洁。

格式:参数,箭头,代码

(参数名)->{代码}

Lambda表达式体现了“函数式编程思想”——

面向对象的思想:找一个能解决问题的对象,调用对象完成事情。

函数式编程思想:只要结果,不管过程,不在乎是谁做、怎么做。


Lambda表达式的前提——函数式接口。

函数式接口,且只有一个未实现方法,可用注解@FunctionalInterface进行限定。

接口有且只有一个未实现方法,Lambda才能进行推导。

可以有其它非抽象方法,比如默认方法。


lambda表达式可推导、可省略:

  • 参数类型可以不写
  • 参数只有一个的话,类型和()都可以省略
  • 如果{}中的代码只有一行,可以省略{}、return、分号
package ah;
import java.util.*;
public class TestLambda {
public static void main(String[] args) {
System.out.println("---- 1.线程(无参数)");
// |--(1.1)匿名内部类写法
Thread t = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread());
}
});
t.start();
// |--(1.2)Lambda表达式写法
Thread t2 = new Thread(() -> {
System.out.println(Thread.currentThread());
});
t2.start();
System.out.println("---- 2.集合排序(带参数)");
List<Phone> lst = new ArrayList<>();
lst.add(new Phone(1000, 300));
lst.add(new Phone(2000, 200));
lst.add(new Phone(3000, 100));
// |--(2.1)匿名内部类写法
Collections.sort(lst, new Comparator<Phone>() {
@Override
public int compare(Phone o1, Phone o2) {
return (int) (o2.price - o1.price);
}
});
System.out.println(lst);
// |--(2.2)Lambda表达式写法
Collections.sort(lst, (Phone o1, Phone o2) -> {
return o2.hot - o1.hot;
});
System.out.println(lst);
// |--(2.3)Lambda表达式省略写法(参数类型省略,{}、return、分号省略)
Collections.sort(lst, (o1, o2) -> o1.hot - o2.hot);
System.out.println(lst);
System.out.println("---- 3.一个参数的场合:参数括号能省略");
// |--(3.1)输出集合内容
lst.forEach(s -> System.out.println(s));
// |--(3.2)自定义接口和方法,参数使用接口
testArgIsInterface(s -> System.out.println(s), 100);
}
static void testArgIsInterface(IoneArg arg, int n) {
arg.m(n);
}
}
class Phone {
double price;
int hot;
public Phone(double price, int hot) {
this.price = price;
this.hot = hot;
}
@Override
public String toString() {
return "Phone [price=" + price + ", hot=" + hot + "]";
}
}
@FunctionalInterface
interface IoneArg {
void m(int n);
}
---- 1.线程(无参数)
Thread[Thread-0,5,main]
---- 2.集合排序(带参数)
Thread[Thread-1,5,main]
[Phone [price=3000.0, hot=100], Phone [price=2000.0, hot=200], Phone [price=1000.0, hot=300]]
[Phone [price=1000.0, hot=300], Phone [price=2000.0, hot=200], Phone [price=3000.0, hot=100]]
[Phone [price=3000.0, hot=100], Phone [price=2000.0, hot=200], Phone [price=1000.0, hot=300]]
---- 3.一个参数的场合:参数括号能省略
Phone [price=3000.0, hot=100]
Phone [price=2000.0, hot=200]
Phone [price=1000.0, hot=300]
100

Supplier接口

java.util.function 包下有很多函数式接口,比如:

@FunctionalInterface
public interface Supplier<T> {
T get();
}

Supplier接口称为“生产型接口”,指定接口的泛型,get方法会产生相应类型的数据。

使用示例:

import java.util.function.Supplier;
public class TestSupplier {
// 将Supplier类型作为参数,以便Lambda知道接口类型
// 要实现的功能:获取数组的最大值
static int getMax(Supplier<Integer> sup) {
return sup.get();
}
public static void main(String[] args) {
int arr[] = { 5, 3, 2, -5, 99, 76 };
int maxOfArr = getMax(() -> {
int max = arr[0];
for (int n : arr) {
max = max < n ? n : max;
}
return max;
});
System.out.println(maxOfArr);
}
}
99

Consumer接口

和Supplier接口相对,用于“消费”,接受参数用于处理。addThen方法用于连续处理。

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

Consumer示例:

import java.util.function.Consumer;
public class TestConsumer {
public static void main(String[] args) {
testAccept((str) -> {
System.out.println(str);
}, "孙行者");
testAndThen((str) -> System.out.println("A" + str),
(str) -> System.out.println(str + "Z"), "猪悟能");
}
static void testAccept(Consumer<String> c, String s) {
// accept接受数据:可以使用数据(相当于消费)
c.accept(s);
}
static void testAndThen(Consumer<String> c1, Consumer<String> c2, String s) {
c1.accept(s);
c2.accept(s);
System.out.println("---default andThen:相当于把两个Consumer连起来使用");
c1.andThen(c2).accept(s);
System.out.println("---连接分先后,参数为后");
c2.andThen(c1).accept(s);
}
}

孙行者

A猪悟能

猪悟能Z

---default andThen:相当于把两个Consumer连起来使用

A猪悟能

猪悟能Z

---连接分先后,参数为后

猪悟能Z

A猪悟能

Predicate接口

predicate:谓词。指boolean-valued,主要有ADD,OR,NOT

源码:

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

示例:对字符串进行判断

import java.util.function.Predicate;
public class TestPredicate {
static void testTest(Predicate<String> p, String s) {
System.out.println(p.test(s));
}
static void testAnd(Predicate<String> p1, Predicate<String> p2, String s) {
System.out.println(p1.and(p2).test(s));
}
public static void main(String[] args) {
testTest((s) -> s == null, "A");
// 判断字符串不为null,同时长度>5
testAnd(
// 参数1:判断不为null
(s) -> s != null,
// 参数2:判断长度>5
(s) -> s.length() > 5,
// 参数3:
"123456");
}
}
false
true

示例:

import java.util.*;
import java.util.function.Predicate;
public class TestPredicate2 {
// 对数组进行过滤,把符合条件的放入集合中
static List<String> filter(Predicate<String> p1, Predicate<String> p2,
String[] arr) {
List<String> lst = new ArrayList<>();
for (String str : arr) {
if (p1.and(p2).test(str)) {
lst.add(str);
}
}
return lst;
}
public static void main(String[] args) {
String[] s = { "关羽,蜀,武", "张飞,蜀,武", "典韦,魏,武", "诸葛亮,蜀,文" };
// 将蜀国的文官放入列表
List<String> lst = filter(
// 参数1:一种操作
(name) -> {
String[] split = name.split(",");
String nation = split[1];
if ("蜀".equals(nation)) {
return true;
} else {
return false;
}
},
// 参数2:另一种操作
(name) -> name.split(",")[2].equals("文"),
// 参数3:被操作的字符串
s);
System.out.println(lst);
}
}
[诸葛亮,蜀,文]

Function接口

根据一个类型的数据(前置条件)得到另一个类型的数据(后置条件)。

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

示例:

import java.util.function.Function;
public class TestFunction {
static void testApply(Function<String, Integer> f, String s) {
Integer n = f.apply(s);
System.out.println(n);
}
static void testAddThen(Function<String, String> f1,
Function<String, String> f2, Function<String, String> f3, String s) {
// compose:组合,先做
// addThen:后做
String ret = f1.compose(f2).andThen(f3).apply(s);
System.out.println(ret);
}
public static void main(String[] args) {
String str = ">>1234";
testApply(
// 参数1:把字符串转换为整数
s -> {
s = s.substring(2);
return Integer.parseInt(s);
},
// 参数2:要处理的字符串
str);
testAddThen(
// 参数1
s -> s + "【齐天大圣】",
// 参数2:做了compose的参数(先做)
s -> s + "【弼马温】",
// 参数3:做了andThen参数(后做)
s -> s + "【斗战胜佛】",
// 参数四:字符串
"孙悟空");
}
}
1234
孙悟空【弼马温】【齐天大圣】【斗战胜佛】

延迟执行

有些场景下,代码执行后,结果不一定被使用,这将造成浪费。Lambda表达式是“延迟执行”的,正好作为解决方案,提升性能。

比如:

public class TestLambdaLazy {
// 非Lambda参数,会产生字符串
public static void log(int level, String msg) {
if (level == 1) {
System.out.println(msg);
}
}
// Lambda表达式写法:参数改为函数式接口
// 参数虽然传递(对象),但是不使用的时候不执行
public static void log(int level, Message msg) {
if (level == 1) {
System.out.println(msg.setMsg());
}
}
public static void main(String[] args) {
int sum = 100;
log(2, "总计:" + sum);// 其实没有打印,字符串徒劳拼接
log(2, () -> {
System.out.println("Lambda执行");
return "总计:" + sum;
});
}
}
// Lambda用的函数式接口
interface Message {
String setMsg();
}

Java基础教程——Lambda表达式的更多相关文章

  1. Java基础语法-Lambda表达式

    1.Lambda表达式主要用于简写接口的操作等出现匿名内部类的地方,如下:我这里先定义一个Swim接口,以及它所定义的swim()方法 interface Swim{ void swim(); } 2 ...

  2. Java基础教程(8)--表达式、语句和块

    一.表达式   表达式由变量和运算符组成.下面是一个简单的赋值表达式: a = 0;   表达式都具有运算结果,因为赋值表达式的运算结果是左侧操作数的值,因此上面的表达式将会返回一个0.可以使用简单的 ...

  3. Java基础教程:Lambda表达式

    Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...

  4. Java 终于有 Lambda 表达式啦~Java 8 语言变化——Lambda 表达式和接口类更改【转载】

    原文地址 en cn 下载 Demo Java™ 8 包含一些重要的新的语言功能,为您提供了构建程序的更简单方式.Lambda 表达式 为内联代码块定义一种新语法,其灵活性与匿名内部类一样,但样板文件 ...

  5. Java基础教程:泛型基础

    Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...

  6. Java 8中Lambda表达式默认方法的模板方法模式,你够了解么?

    为了以更简单的术语描述模板方法,考虑这个场景:假设在一个工作流系统中,为了完成任务,有4个任务必须以给定的执行顺序执行.在这4个任务中,不同工作流系统的实现可以根据自身情况自定义任务的执行内容. 模板 ...

  7. java 8 中lambda表达式学习

    转自 http://blog.csdn.net/renfufei/article/details/24600507 http://www.jdon.com/idea/java/10-example-o ...

  8. Lambda 表达式,Java中应用Lambda 表达式

    一.Lambda 表达式 简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数. 链接:知乎 先举一个普通的 Python 例 ...

  9. Java基础教程(18)--继承

    一.继承的概念   继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...

随机推荐

  1. B. Kay and Snowflake 解析(思維、DFS、DP、重心)

    Codeforce 685 B. Kay and Snowflake 解析(思維.DFS.DP.重心) 今天我們來看看CF685B 題目連結 題目 給你一棵樹,要求你求出每棵子樹的重心. 前言 完全不 ...

  2. 将java的jar包,打包为rpm 安装包

    一.rpm包 介绍 RPM Package Manager (RPM) 是一个强大的命令行驱动的软件包管理工具,用来安装.卸载.校验.查询和更新 Linux 系统上的软件包 二.环境安装 一台cent ...

  3. Go的第一个Hello程序 简简单单 - 快快乐乐

    Go的第一个Hello程序 简简单单 - 快快乐乐 JERRY_Z. ~ 2020 / 10 / 29 转载请注明出处!️ 目录 Go的第一个Hello程序 简简单单 - 快快乐乐 一.Go程序开发基 ...

  4. 走在深夜的小码农 Second Day

    HTML5 Second Day writer:late at night codepeasant 学习大纲 表格 表格的主要作用 表格主要用于显示.展示数据,因为它可以让数据显示的非常的规整,可读性 ...

  5. 4G DTU是什么 4G DTU的功能和特点

    4G DTU是什么 DTU中文名称是"数据传输终端",根据数据传输时使用的传输方式网络的不同,DTU设备又可以分为很多种类,例如:4G DTU.NB-IOT DTU.LORA DT ...

  6. model基础操作(下)

    3.Django多对多表结构操作   3.1 第一种: ManyToManyField   自己不创建第三张关系表,有m2m字段: 根据queryset对象增删改查(推荐)   from django ...

  7. python获取汉字首字母

    获取汉字首字母 关注公众号"轻松学编程"了解更多. 应用场景之一:可用于获取名字首字母,在数据库中查询记录时,可以用它来排序输出. from pytz import unicode ...

  8. 用spring-retry注解自动触发重试方法

    原文地址:https://www.jianshu.com/p/ee02d6125113 需求背景: 有些时候我们再调用一些第三方服务的时候,从第三方那边拉数据. 但是第三方服务不是100%稳定的,有些 ...

  9. leetcode76set-matrix-zeroes

    题目描述 给定一个m*n的矩阵,如果有一个元素是0,就把该元素所在的行和列上的元素全置为0,要求使用原地算法. 拓展: 你的算法有使用额外的空间吗? 一种比较直接的算法是利用O(m,n)的空间,但是这 ...

  10. B/S图书管理系统

    B/S图书管理系统 系统管理 ①新用户注册 ②用户信息修改:修改信息,修改密码 ③锁定用户 ④注销用户 书籍管理 ①新书入库 ②借书办理 ③还书办理 ④书记注销 个人管理 ①图书查询 ②借书单查询 ③ ...