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. web worker的介绍和使用

    目录 简介 Web Workers的基本概念和使用 Web Workers的分类 worker和main thread之间的数据传输 简介 什么是web worker呢?从名字上就可以看出,web w ...

  2. Some problems in openMP's parallel for

    Overview Somehow I started preparing for the ASC competition.When I'm trying my second demo pi, whic ...

  3. K8S的StorageClass实战(NFS)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. 应该怎么提升4G工业路由器的无线信号?

    4G工业路由器如今应用的范围非常的广泛,在实际使用中也遇到了很多的问题,其中经常被问到的一个问题就是我们怎么保证4G工业路由器的良好信号强度.在互联网上也有很多关于如何找到最佳信号的方法,但对于固定和 ...

  5. 【QT】 QThread部分源码浅析

    本文章挑出QThread源码中部分重点代码来说明QThread启动到结束的过程是怎么调度的.其次因为到了Qt4.4版本,Qt的多线程就有所变化,所以本章会以Qt4.0.1和Qt5.6.2版本的源码来进 ...

  6. 【事件中心 Azure Event Hub】Event Hub日志种发现的错误信息解读

    问题描述 使用Event Hub消费事件时,出现的各种客户端错误的解读.(再后期遇见新的错误信息,会持续添加进此说明) 一:再Linux中运行Event Hub消费端程序,出现Too many ope ...

  7. .NET Core 跨平台资源监控库及 dotnet tool 小工具

    目录 简介 dotnet tool 体验 CZGL.SystemInfo SystemPlatformInfo ProcessInfo 内存监控 NetworkInfo DiskInfo 简介 CZG ...

  8. How to using expression setup BackgroundColor AX2012 SSRS Report[AX2012]

    tile label using [#99ccff] property BackgroundColor - > expression =Iif(Fields!Flag.Value = " ...

  9. 完美实现CSS垂直居中的11种方法

    在做前端项目时CSS的水平居中我们经常使用,但有时还会用到CSS垂直居中,对于小白来说这个就有些难度了,下面看一下我是如何实现的 本人前端小白,正在做一个小程序开发的项目,css样式调整搞的头都大了. ...

  10. 激情的来源 Imagine how much you love it !

    激情来自哪里?我想可能我找到了,精髓就在那个标题! 想象你有多么爱它!你就会爱上他,想象你有多么喜欢某一个东西,你很有可能就喜欢上他,着手去了解他,接触他. 如果带着这种想象状态的激情,工作和学习会有 ...