10.1、函数式接口
10.1.1、概述
有且仅有一个抽象方法的接口,并且可以通过在类上标注@FunctionalInterface注解进行检测,建议自定义的函数式接口都加上这个注解
10.1.2、函数式接口作为方法的参数
public class Main {
public static void main(String[] args) {
// 匿名内部类的方式
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程启动了");
}
});
// Lambda表达式方式
startThread(() -> System.out.println(Thread.currentThread().getName() + "线程启动了"));
}
private static void startThread(Runnable r) {
new Thread(r).start();
}
}
10.1.3、函数式接口作为方法的返回值
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class Main {
public static void main(String[] args) {
ArrayList array1 = new ArrayList();
array1.add("cccc");
array1.add("aaa");
array1.add("bb");
array1.add("d");
System.out.println("排序前:" + array1);
Collections.sort(array1, getComparator1());
System.out.println("排序后:" + array1);
ArrayList array2 = new ArrayList();
array2.add("cccc");
array2.add("aaa");
array2.add("bb");
array2.add("d");
System.out.println("排序前:" + array2);
Collections.sort(array2, getComparator2());
System.out.println("排序后:" + array2);
}
// 匿名内部类的方式实现
private static Comparator getComparator1() {
return new Comparator() {
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
};
}
// Lambda表达式方式实现
private static Comparator getComparator2() {
return (s1, s2) -> s1.length() - s2.length();
}
}
10.1.4、四大内置核心函数式接口
10.1.4.1、Supplier接口
import java.util.function.Supplier;
public class Main {
public static void main(String[] args) {
String s = getString(() -> "林青霞");
System.out.println(s);
Integer i = getInteger(() -> 30);
System.out.println(i);
}
// 定义一个方法,返回一个整数数据
private static Integer getInteger(Supplier sup) {
return sup.get();
}
// 定义一个方法,返回一个字符串数据
private static String getString(Supplier sup) {
return sup.get();
}
}
10.1.4.2、Consumer接口
import java.util.function.Consumer;
public class Main {
public static void main(String[] args) {
operatorString("林青霞", s -> System.out.println(s));
operatorString("林青霞", s -> System.out.println(new StringBuilder(s).reverse().toString()));
operatorString("林青霞",
s -> System.out.println(s),
s -> System.out.println(new StringBuilder(s).reverse().toString()));
}
// 定义一个方法,消费同一个字符串数据两次
private static void operatorString(String name, Consumer con1, Consumer con2) {
// con1.accept(name);
// con2.accept(name);
con1.andThen(con2).accept(name);
}
// 定义一个方法,消费同一个字符串数据一次
private static void operatorString(String name, Consumer con) {
con.accept(name);
}
}
10.1.4.3、Predicate接口
import java.util.function.Predicate;
public class Main {
public static void main(String[] args) {
boolean b1 = checkString("helloworld", s -> s.length() > 8);
System.out.println(b1);
boolean b2 = checkStringNot("helloworld", s -> s.length() > 8);
System.out.println(b2);
boolean b3 = checkStringAnd("helloworld", s -> s.length() > 8, s -> s.length() < 10);
System.out.println(b3);
boolean b4 = checkStringOr("helloworld", s -> s.length() > 8, s -> s.length() < 10);
System.out.println(b4);
}
// 定义一个方法,对给定的参数进行判断
private static boolean checkString(String s, Predicate pre) {
return pre.test(s);
}
// 定义一个方法,返回一个逻辑的否定,对应逻辑非
private static boolean checkStringNot(String s, Predicate pre) {
return pre.negate().test(s);
}
// 定义一个方法,返回一个组合判断,对应短路与
private static boolean checkStringAnd(String s, Predicate pre1, Predicate pre2) {
return pre1.and(pre2).test(s);
}
// 定义一个方法,返回一个组合判断,对应短路或
private static boolean checkStringOr(String s, Predicate pre1, Predicate pre2) {
return pre1.or(pre2).test(s);
}
}
10.1.4.4、Function接口
import java.util.function.Function;
public class Main {
public static void main(String[] args) {
convert("100", s -> Integer.parseInt(s));
convert(100, i -> String.valueOf(i));
convert("100", s -> Integer.parseInt(s), i -> String.valueOf(i));
}
// 定义一个方法,把一个字符串转换为int类型,在控制台输出
private static void convert(String s, Function fun) {
int i = fun.apply(s);
System.out.println(i);
}
// 定义一个方法,把一个int类型转换为字符串,在控制台输出
private static void convert(int i, Function fun) {
String s = fun.apply(i);
System.out.println(s);
}
// 定义一个方法,把一个字符串转换为int类型,把一个int类型转换为字符串,在控制台输出
private static void convert(String s, Function fun1, Function fun2) {
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
}
}
10.2、Stream流
10.2.1、概述
流(Stream)是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。集合讲的是数据,流讲的是计算
10.2.2、操作步骤
-
获流对象:一个数据源(如:集合、数组),获取一个流(如:串行流、并行流、无限流)
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; public class Main { public static void main(String[] args) { // Collection体系的集合直接生成流 List
list = new ArrayList (); Stream listStream = list.stream();// 顺序流 Stream parallelListStream = list.parallelStream(); // 并行流 Set set = new HashSet (); Stream setStream = set.stream();// 顺序流 Stream parallelSetStream = set.parallelStream();// 并行流 // Map体系的集合间接生成流 Map map = new HashMap (); Stream keyStream = map.keySet().stream();// 顺序流 Stream parallelKeyStream = map.keySet().parallelStream();// 并行流 Stream valueStream = map.values().stream();// 顺序流 Stream parallelValueStream = map.values().parallelStream();// 并行流 Stream > entryStream = map.entrySet().stream();// 顺序流 Stream > parallelEntryStreamStream = map.entrySet().parallelStream();// 并行流 // 数组可以通过Arrays类的静态方法Arrays.stream(T[] array)生成流 int[] intArray = { 10, 20, 30 }; IntStream intStream = Arrays.stream(intArray);// 顺序流 IntStream parallelIntStream = intStream.parallel();// 并行流 long[] longArray = { 10L, 20L, 30L }; LongStream longStream = Arrays.stream(longArray);// 顺序流 LongStream parallelLongStream = longStream.parallel();// 并行流 double[] doubleArray = { 10.1, 20.2, 30.3 }; DoubleStream doubleStream = Arrays.stream(doubleArray);// 顺序流 DoubleStream parallelDoubleStream = doubleStream.parallel();// 并行流 // 数组可以通过Stream接口的静态方法Stream.of(T... values)生成流 Stream strArrayStream = Stream.of("hello", "world", "java");// 顺序流 Stream parallelStrArrayStream = strArrayStream.parallel();// 并行流 Stream intArrayStream = Stream.of(10, 20, 30);// 顺序流 Stream parallelIntArrayStream = intArrayStream.parallel();// 并行流 Stream longArrayStream = Stream.of(10L, 20L, 30L);// 顺序流 Stream parallelLongArrayStream = longArrayStream.parallel();// 并行流 Stream doubleArrayStream = Stream.of(10.1, 20.2, 30.3);// 顺序流 Stream parallelDoubleArrayStream = doubleArrayStream.parallel();// 并行流 // 创建无限流 Stream iterateStream = Stream.iterate(0, i -> i + 2); iterateStream.limit(10).forEach(System.out::println); Stream generateStream = Stream.generate(UUID::randomUUID); generateStream.limit(10).forEach(System.out::println); } } -
中间操作:一个中间操作链,对数据源的数据进行处理
- filter()
- limit()
- skip()
- distinct()
- sorted()
- map()
- mapToInt()
- mapToLong()
- mapToDouble()
- flatMap()
- flatMapToInt()
- flatMapToLong()
- flatMapToDouble()
- peek()
-
终止操作:一个终止操作,执行中间操作链并产生结果
- forEach()
- forEachOrdered()
- count()
- min()
- max()
- reduce()
- collect()
- toArray()
- findFirst()
- findAny()
- anyMatch()
- allMatch()
- noneMatch()
10.2.3、代码演示
filter代码演示:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个集合,存储多个字符串元素
ArrayList list = new ArrayList();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
// 需求1:把list集合中以张开头的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
System.out.println("----------");
// 需求2:把list集合中长度为3的元素在控制台输出
list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
System.out.println("----------");
// 需求3:把list集合中以张开头的且长度为3的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
}
}
limit&skip代码演示:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个集合,存储多个字符串元素
ArrayList list = new ArrayList();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
// 需求1:取前3个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);
System.out.println("----------");
// 需求2:跳过3个元素,把剩下的元素在控制台输出
list.stream().skip(3).forEach(System.out::println);
System.out.println("----------");
// 需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);
}
}
distinct代码演示:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个集合,存储多个字符串元素
ArrayList list = new ArrayList();
list.add("林青霞");
list.add("林青霞");
list.add("张曼玉");
list.add("张曼玉");
list.add("王祖贤");
list.add("王祖贤");
list.add("柳岩");
list.add("柳岩");
list.add("张敏");
list.add("张敏");
list.add("张无忌");
list.add("张无忌");
// 需求1:把集合元素在控制台输出,要求字符串元素不能重复
list.stream().distinct().forEach(System.out::println);
}
}
sorted代码演示:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个集合,存储多个字符串元素
ArrayList list = new ArrayList();
list.add("linqingxia");
list.add("zhangmanyu");
list.add("wangzuxian");
list.add("liuyan");
list.add("zhangmin");
list.add("zhangwuji");
// 需求1:按照字母顺序把数据在控制台输出
list.stream().sorted().forEach(System.out::println);
System.out.println("----------");
// 需求2:按照字符串长度把数据在控制台输出
list.stream().sorted((s1, s2) -> {
int num1 = s1.length() - s2.length();
int num2 = num1 == 0 ? s1.compareTo(s2) : num1;
return num2;
}).forEach(System.out::println);
}
}
map&mapToInt&mapToLong&mapToDouble代码演示:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个集合,存储多个字符串元素
ArrayList list = new ArrayList();
list.add("10");
list.add("20");
list.add("30");
list.add("40");
list.add("50");
// 需求1:将集合中的字符串数据转换为整数之后在控制台输出
list.stream().map(Integer::parseInt).forEach(System.out::println);
System.out.println("----------");
// 需求2:将集合中的字符串数据转换为Integer之后在控制台输出
list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);
System.out.println("----------");
// 需求3:将集合中的字符串数据转换为Long之后在控制台输出
list.stream().mapToLong(Long::parseLong).forEach(System.out::println);
System.out.println("----------");
// 需求4:将集合中的字符串数据转换为Double之后在控制台输出
list.stream().mapToDouble(Double::parseDouble).forEach(System.out::println);
}
}
forEach&forEachOrdered&count代码演示:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个集合,存储多个字符串元素
ArrayList list = new ArrayList();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
// 需求1:把集合中的元素在控制台输出
list.stream().forEach(System.out::println);
System.out.println("----------");
// 需求2:把集合中的元素在控制台输出
list.stream().forEachOrdered(System.out::println);
System.out.println("----------");
// 需求3:统计集合中有几个以张开头的元素,并把统计结果在控制台输出
long count = list.stream().filter(s -> s.startsWith("张")).count();
System.out.println(count);
}
}
max&min代码演示:
import java.util.ArrayList;
public class Main {
public static void main(String[] args) {
// 创建一个集合,存储多个整数元素
ArrayList list = new ArrayList();
list.add(10);
list.add(20);
list.add(30);
list.add(40);
list.add(50);
// 需求1:获取集合中的最大值在控制台输出
Integer max = list.stream().max(Integer::compareTo).get();
System.out.println(max);
// 需求2:获取集合中的最小值在控制台输出
Integer min = list.stream().min(Integer::compareTo).get();
System.out.println(min);
}
}