一、Lambda表达式(1.8特性)
函数式编程始终编程方式,它将电脑视为函数的计算。将业务逻辑细化、抽象、封装成一个个功能函数(方法),并借助语言自带的高阶函数,将整个业务流程转化为函数之间的相互调用,这就是函数是编程。Lambda表达式是接口的匿名内部类替代品,但必须只有一个抽象方法要实现(匿名内部类目的也是对抽象方法的实现)。
函数式接口:符合定义Lambda表达式的接口
Lambda语法格式 三部分
- 参数 【抽象方法的参数列表,与常规方法一致 无参数留空,多个参数用逗号分隔】
- -> 【新引入的语法格式 】
- 代码体 【方法实现的代码块 逻辑实现体 】
标准格式:(参数类型 参数名称)->{ 代码体 }
【代码】比较器 (数组排序、HashSet、TreeSet 构造时需要构造器)
参数列表的省略原则:参数类型可省略;参数为一个时候 (a) ->{} 可省略为 a ->{} ;无参数时 不能省 ()->{}
方法体的省略原则:大括号内只有一条执行语句,{} ; return 3个一省全省。 ()->{return a-b;} 省略后。()-> a-b
如: (Person o1, Person o2) -> { return o2.age - o1.age;}// 简化后(o1, o2) -> o2.age - o1.age
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
public class DemoLambda {
// Lambda 1.8 JDK 新特性 函数编程 高阶调用低阶函数
// Stream 1.8 JDK 新特性
/*前提:是接口匿名内部类替代品、必须只有一个抽象方法实现,这种符合Lambda表达式接口 称之为 函数式接口
格式:( 参数类型, 参数名称 )-> { 代码语句 }*/
public static void main(String[] args) {
// 比较器 (数组排序、HashSet、TreeSet 构造时需要构造器)
Person[] pers = new Person[3];
pers[0] = new Person("张三", 12);
pers[1] = new Person("李四", 9);
pers[2] = new Person("王五", 15);
Arrays.sort(pers, new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.age - o2.age;
}
});
for (Person per : pers) {
System.out.println("per = " + per);
}
// 比较器简化后 (标准格式) (参数列表)-> { 代码体 }
Arrays.sort(pers, (Person o1, Person o2) -> {
return o2.age - o1.age;
}
);
//比较器简化后 (省略格式)
Arrays.sort(pers, (o1, o2) -> o2.age - o1.age);
for (Person per : pers) {
System.out.println("per = " + per);
}
}
}
class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';
}
}
二、函数式接口
1、函数式接口的特点
@FunctionalInterface // 注解 语法限定 对函数式接口的限定,只能有一个需要实现的抽象方法
interface Calculator{ //自定义接口
int calculate(int a ,int b); // 抽象方法的定义
// 可以有其他的静态、默认方法
}
【代码】自定义函数式接口
public class DemoFuncInterface {
public static void main(String[] args) {
// 1 重写接口方法体、获取接口对象
Calculator c1 = (a,b)->a+b;
// 2 函数调用
int res1 = c1.calculate(100, 200);
// 3 展示结果
System.out.println("res1 = " + res1);
// 明确输入与输出 (自定义函数规则)
Calculator c2 = (a,b)->a*b;
int res2 = c2.calculate(19, 6);
System.out.println("res2 = " + res2);
}
}
// 注解 对函数式接口的限定,只能有一个需要实现的抽象方法
@FunctionalInterface
interface Calculator{
int calculate(int a ,int b);
}
2、Supplier <JDK提供>
java.util.function.Supplier<T> 是一个供给型接口、接口中包含一个T get() 方法,用来获取一个范型参数指定类型的数据对象(应用场景:数据提供)
【代码】获取 【1-100】的随机数
import java.util.Random;
import java.util.function.Supplier;// JDK自有 供给型接口
/*Supplier 接口是一个供给型接口 可以用来提供执行类型的数据 获取逻辑具体在get()中实现*/
public class DemoSupplier {
public static void main(String[] args) {
// JDK自有 供给型接口 【赘余版】
Supplier<Integer> demo = new Supplier<Integer>() {
@Override
public Integer get() {
return new Random().nextInt(10);
}
};
// 【简化版】 案例:获取 【1-100】的随机数
Supplier<Integer> sup = () -> {
// (重要) 提供标准格式内容
Random r = new Random();
int num = r.nextInt(100) + 1;
return num;
};
for (int i = 0; i < 10; i++) {
Integer res = sup.get();
System.out.println("res" + i + " = " + res);
}
// 简化
Supplier<Integer> supSim = () -> new Random().nextInt(100) + 1;
for (int i = 0; i < 10; i++) {
Integer res = sup.get();
System.out.println("Sim res" + i + " = " + res);
}
}
}
3、Consumer <JDK提供>
java.util.function.Consumer<T> 接口是一个消费型接口,实现抽象方法 void accept(T t) 对传入的数据t进行处理【应用场景:对数据的标准化处理】
【代码】字符串列表按照指定格式输出
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;
/*Consumer 一个消费型接口 实现accept(T t) 对传入的数据t进行逻辑加工处理*/
public class DemoConsumer {
public static void main(String[] args) {
// 创建list对象
ArrayList<String> list = new ArrayList<>();
boolean bo = Collections.addAll(list, "肖生克的救赎", "罗马假日", "School", "五福临门");
System.out.println("bo = " + bo); // 全部添加成功
// 按照规定格式处理 ()
ArrayList<String> result = new ArrayList<>();
// 【赘余版】
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println("赘余 s = " + s);
}
});
// 【简化版】
list.forEach((s) -> {
//(重要) 此处可对接收的对象进行加工处理
System.out.println("《" + s + "》");
result.add("《" + s + "》");
});
System.out.println("result = " + result);//result = [《肖生克的救赎》, 《罗马假日》, 《School》, 《五福临门》]
/*
目前list集合遍历的方式:
1 普通for循环;2 增强for;3 迭代器Iterator; 4 list.forEach()
*/
}
}
3、Predicate <JDK提供>
java.util.function.Predicate<T> 接口可以实现对某种类型的数据进行判断,实现抽象方法 boolean test(T t) 对传入的数据逻辑判定【应用场景:数据合法性判断】
【代码】对数字进行奇偶判断 并添加至对应列表
import java.util.ArrayList;
import java.util.Random;
import java.util.function.Predicate;
/*Predicate 实现对某种类型的判断、返回boolean 具体逻辑由test(T t)进行判断实现 */
public class DemoPredicate {
static ArrayList<Integer> odd = new ArrayList<>(); // 奇数
static ArrayList<Integer> even = new ArrayList<>();// 偶数
public static void main(String[] args) {
// 随机生成10个数据,按照奇偶添加到不同的列表
Random random = new Random();
int[] arr = new int[10];
for (int i = 0; i < 10; i++) {
arr[i] = random.nextInt(100);
}
// 【赘余版】 predicate 偶数-> true
for (int i : arr) {
analyze(i, new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer % 2 == 0;
}
});
}
// 【简化版】
for (int i : arr) {
analyze(i, x -> x % 2 == 0);
}
// 查看结构
System.out.println("偶数 even = " + even);
System.out.println("奇数 odd = " + odd);
}
public static void analyze(int num, Predicate<Integer> predicate) {
if (predicate.test(num)) {
even.add(num);
} else {
odd.add(num);
}
}
}
5、Function<JDK提供>
java.util.function.Function<T, R> 接口可以实现将一种数据类型T转变为另一种数据类型R,实现抽象方法 R apply(T t) 将传入的数据类型T 转为R 【应用场景:数据类型转变】
【代码】字符串装变为指定类对象
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;
/*魔法师 将一种类型T转变成另外一种类型R的结构 具体由R apply(T t)方法实现
java.util.function.Function<T, R>{ // T->R
R apply(T t);
} */
public class DemoFunction {
public static void main(String[] args) {
// 案例 将字符串转变成对象
// 准备字符串
ArrayList<String> list = new ArrayList<>();
boolean b = Collections.addAll(list, "小红:18", "小明:17", "大黄:19");
System.out.println("字符串添加情况 : " + b);
// 【赘余版】
for (String p : list) {
map(p, new Function<String, Person>() {
@Override
public Person apply(String s) {
String[] splits = s.split(":");
Person person = new Person(splits[0], Integer.parseInt(splits[1]));
return person;
}
});
}// end for
// 【简化版】
for (String p : list) {
map(p,(s -> {
String[] splits = s.split(":");
return new Person(splits[0],Integer.parseInt(splits[1]));
}));
}// end for
}// end main
public static void map(String str, Function<String, Person> function) {
// 调用接口实例函数
Person person = function.apply(str);
System.out.println("person = " + person);
}
}
三、Stream流
得益于Lambda所带来的函数式编程,引入全新的Stream概念(写出优雅的代码)
| 方法名 | 方法作用 | 方法种类 | 是否支持链式调用 | |
| count | 统计个数 | long cout(); | 终结 | 否 |
| forEach | 逐一处理 | void forEach(Consumer <? super T> action); | 终结 | 否 |
| filter | 过滤 | Stream<T> filter(Predicate <? super T> predicate) ; | 函数拼接 | 是 |
| limit | 取用前几个 | Stream<T> limit(long maxSize); | 函数拼接 | 是 |
| skip | 跳过前几个 | Stream<T> skip(long n) ; | 函数拼接 | 是 |
| map | 映射 | <R> Stream map( Function<? super T, ?extends R> mapper ); | 函数拼接 | 是 |
| concat | 组合 | static <T>Stream concat( Stream<? extends a, ?extends T> b ); | 函数拼接 | 是 |
import java.util.ArrayList;
import java.util.Collections;
public class DemoStream {
public static void main(String[] args) {
// 所有的Collection集合 都默认 stream() 方法获取流
ArrayList<String> list = new ArrayList<>();
boolean boo = Collections.addAll(list, "张三", "张三丰", "王二小", "李铁牛", "黄继光");
System.out.println("boo = " + boo);// 添加成功否
// 姓张 两个子的有几个人
long num = list.stream()
.filter(s -> s.startsWith("张"))
.filter(s -> s.length() == 2)
.count();
}
}
收集Stream结果
对流操作完之后,如果需要将其结果保存至集合、数组等
【代码】收集至 List Set Array
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class DemoCollectors {
public static void main(String[] args) {
// 成为list
Stream<String> s1 = Stream.of("A", "B", "C", "D");
List<String> list = s1.collect(Collectors.toList());
System.out.println("list = " + list);
// 成为set
Stream<String> s2 = Stream.of("A", "B", "C", "D");
Set<String> set = s2.collect(Collectors.toSet());
System.out.println("set = " + set);
// 成为Array
Stream<String> s3 = Stream.of("A", "B", "C", "D");
Object[] objects = s3.toArray();
}
}
本文介绍了Java 1.8引入的Lambda表达式,作为函数式编程的基础,以及函数式接口的使用,涵盖了Comparator、Supplier、Consumer、Predicate和Function接口的应用实例。同时展示了Stream流的概念和操作,如过滤、映射和计数。
1万+

被折叠的 条评论
为什么被折叠?



