Java基础教程——Lambda表达式
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表达式的更多相关文章
- Java基础语法-Lambda表达式
		
1.Lambda表达式主要用于简写接口的操作等出现匿名内部类的地方,如下:我这里先定义一个Swim接口,以及它所定义的swim()方法 interface Swim{ void swim(); } 2 ...
 - Java基础教程(8)--表达式、语句和块
		
一.表达式 表达式由变量和运算符组成.下面是一个简单的赋值表达式: a = 0; 表达式都具有运算结果,因为赋值表达式的运算结果是左侧操作数的值,因此上面的表达式将会返回一个0.可以使用简单的 ...
 - Java基础教程:Lambda表达式
		
Java基础教程:Lambda表达式 本文部分内容引用自OneAPM:http://blog.oneapm.com/apm-tech/226.html 引入Lambda Java 是一流的面向对象语言 ...
 - Java 终于有 Lambda 表达式啦~Java 8 语言变化——Lambda 表达式和接口类更改【转载】
		
原文地址 en cn 下载 Demo Java™ 8 包含一些重要的新的语言功能,为您提供了构建程序的更简单方式.Lambda 表达式 为内联代码块定义一种新语法,其灵活性与匿名内部类一样,但样板文件 ...
 - Java基础教程:泛型基础
		
Java基础教程:泛型基础 引入泛型 传统编写的限制: 在Java中一般的类和方法,只能使用具体的类型,要么是基本数据类型,要么是自定义类型.如果要编写可以应用于多种类型的代码,这种刻板的限制就会束缚 ...
 - Java 8中Lambda表达式默认方法的模板方法模式,你够了解么?
		
为了以更简单的术语描述模板方法,考虑这个场景:假设在一个工作流系统中,为了完成任务,有4个任务必须以给定的执行顺序执行.在这4个任务中,不同工作流系统的实现可以根据自身情况自定义任务的执行内容. 模板 ...
 - java 8 中lambda表达式学习
		
转自 http://blog.csdn.net/renfufei/article/details/24600507 http://www.jdon.com/idea/java/10-example-o ...
 - Lambda 表达式,Java中应用Lambda 表达式
		
一.Lambda 表达式 简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数. 链接:知乎 先举一个普通的 Python 例 ...
 - Java基础教程(18)--继承
		
一.继承的概念 继承是面向对象中一个非常重要的概念,使用继承可以从逻辑和层次上更好地组织代码,大大提高代码的复用性.在Java中,继承可以使得子类具有父类的属性和方法或者重新定义.追加属性和方法. ...
 
随机推荐
- B. Kay and Snowflake 解析(思維、DFS、DP、重心)
			
Codeforce 685 B. Kay and Snowflake 解析(思維.DFS.DP.重心) 今天我們來看看CF685B 題目連結 題目 給你一棵樹,要求你求出每棵子樹的重心. 前言 完全不 ...
 - 将java的jar包,打包为rpm 安装包
			
一.rpm包 介绍 RPM Package Manager (RPM) 是一个强大的命令行驱动的软件包管理工具,用来安装.卸载.校验.查询和更新 Linux 系统上的软件包 二.环境安装 一台cent ...
 - Go的第一个Hello程序 简简单单 - 快快乐乐
			
Go的第一个Hello程序 简简单单 - 快快乐乐 JERRY_Z. ~ 2020 / 10 / 29 转载请注明出处!️ 目录 Go的第一个Hello程序 简简单单 - 快快乐乐 一.Go程序开发基 ...
 - 走在深夜的小码农 Second Day
			
HTML5 Second Day writer:late at night codepeasant 学习大纲 表格 表格的主要作用 表格主要用于显示.展示数据,因为它可以让数据显示的非常的规整,可读性 ...
 - 4G DTU是什么  4G DTU的功能和特点
			
4G DTU是什么 DTU中文名称是"数据传输终端",根据数据传输时使用的传输方式网络的不同,DTU设备又可以分为很多种类,例如:4G DTU.NB-IOT DTU.LORA DT ...
 - model基础操作(下)
			
3.Django多对多表结构操作 3.1 第一种: ManyToManyField 自己不创建第三张关系表,有m2m字段: 根据queryset对象增删改查(推荐) from django ...
 - python获取汉字首字母
			
获取汉字首字母 关注公众号"轻松学编程"了解更多. 应用场景之一:可用于获取名字首字母,在数据库中查询记录时,可以用它来排序输出. from pytz import unicode ...
 - 用spring-retry注解自动触发重试方法
			
原文地址:https://www.jianshu.com/p/ee02d6125113 需求背景: 有些时候我们再调用一些第三方服务的时候,从第三方那边拉数据. 但是第三方服务不是100%稳定的,有些 ...
 - leetcode76set-matrix-zeroes
			
题目描述 给定一个m*n的矩阵,如果有一个元素是0,就把该元素所在的行和列上的元素全置为0,要求使用原地算法. 拓展: 你的算法有使用额外的空间吗? 一种比较直接的算法是利用O(m,n)的空间,但是这 ...
 - B/S图书管理系统
			
B/S图书管理系统 系统管理 ①新用户注册 ②用户信息修改:修改信息,修改密码 ③锁定用户 ④注销用户 书籍管理 ①新书入库 ②借书办理 ③还书办理 ④书记注销 个人管理 ①图书查询 ②借书单查询 ③ ...