概念:有且仅有一个抽象方法的接口就叫做函数式接口。可以使用@FunctionalInterface注解检查。
注意:一个接口是不是函数式接口和@FunctionalInterface没有任何关系,只和抽象方法的个数有关。如果这个接口不是函数式接口,
那么加上这个注解之后就会编译报错。
例如:JDK中的Runnable接口就是一个函数式接口
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
使用场景:作为方法的参数或者返回值
JDK中常见的函数式接口
Supplier:生产型接口
T get():get()
方法不需要给参数,反而给你返回一个T类型的值。
package com.jxufe_ldl.class02.supplier;
import java.util.function.Supplier;
public class SupplierDemo {
public static void main(String[] args) {
// 获取一个字符串
String str = getString(() -> "于曼丽");
System.out.println("str = " + str);
// 获取一个整数
int num = getInt( () -> 666);
System.out.println("num = " + num);
}
private static String getString(Supplier<String> sup) {
return sup.get();
}
private static int getInt(Supplier<Integer> sup) {
return sup.get();
}
}
Consumer:消费型接口
void accept(T t):
需要一个T类型的参数,没有返回值,通过accept将T类型的数据交给我们使用(消费) (掌握)
default Consumer
:将两个Consumer连接,分别消费数据
例如:
//遍历输出 (T t)
list.forEach(num->System.out.println(num));
System.out.println("--------------");
//方法引用
list.forEach(System.out::println);
```java
package com.jxufe_ldl.class01;
import java.util.function.Consumer;
public class ConsumerDemo {
public static void main(String[] args) {
// 定义一个字符串数组
String[] strArr = {"林青霞,30", "张曼玉,35", "王祖贤,33"};
// 调用方法
printInfo(strArr, (String s) -> {
String name = s.split(",")[0];
System.out.print("姓名:" + name);
}, (String s) -> {
int age = Integer.parseInt(s.split(",")[1]);
System.out.println(",年龄:" + age);
});
}
// Consumer 的泛型指定了什么类型,accept方法消费的数据就是什么类型
private static void printInfo(String[] strArr, Consumer con1, Consumer con2) {
for (String str : strArr) {
con1.andThen(con2).accept(str);
}
}
}
```
Predicate:判断型接口
boolean test(T t)
:将给定的T类型的参数在test方法中进行条件判断,返回判断结果。
package com.jxufe_ldl.class01;
import java.util.function.Predicate;
public class PredicateDemoo02 {
public static void main(String[] args) {
boolean b1= checkString("hello", (String str) -> {
return str.length() > 8;
});
System.out.println(b1);
boolean b2 = checkString("hello", str -> str.length() > 8, str -> str.length() < 15);
System.out.println(b2);
}
// 判断给定的字符串是否满足要求
private static boolean checkString(String str, Predicate<String> pre) {
// return pre.test(str);
return pre.negate().test(str);
}
private static boolean checkString(String str, Predicate<String> pre1, Predicate<String> per2){
// return pre1.or(per2).test(str);
return pre1.and(per2).test(str);
}
}
Function
R apply(T t)
:将T类型的参数传递给方法,转换成R类型之后返回。
package com.jxufe_ldl.class02.supplier;
import java.util.function.Function;
public class FunctionDemo {
public static void main(String[] args) {
String str = "林黛玉,18";
/*convert(str, (String s) -> {
return str.split(",")[1];
}, (String s) -> {
return Integer.parseInt(s);
}, (Integer i) -> {
return i + 70;
});*/
convert(str, s -> str.split(",")[1], Integer::parseInt, i -> i + 70);
}
private static void convert(String str, Function<String,String> fun1, Function<String, Integer> fun2,
Function<Integer, Integer> fun3) {
int i = fun1.andThen(fun2).andThen(fun3).apply(str);
System.out.println(i);
}
}
java.lang.IllegalStateException: stream has already been operated upon or closed
生成Stream流对象
Stream stream=单列集合对象.stream();
Stream stream=Stream.of(T… t);
注意:Map集合必须要先转换成单列集合(keySet()或者entrySet())之后才可以生成Stream流对象。
调用Stream流对象的方法
Stream
用于对流中的数据进行过滤,需要使用Predicate接口传递过滤条件
Stream
截取前指定参数个数的数据,返回截取的元素组成的新流
Stream
跳过指定参数个数的数据,返回由该流的剩余元素组成的新流
static
合并a和b两个流为一个流
Stream
对流中的元素去重(根据Object.equals(Object) )组成的流
Stream
返回由此流的元素组成的流,根据自然顺序排序
Stream
返回由该流的元素组成的流,根据提供的Comparator进行排序
Stream
将流中的数据转换成另一种类型进行存储,返回新的流对象。
Function转换型接口中的方法 R apply(T t)
void forEach(Consumer action):
遍历消费流中的数据
long count():
返回此流中的元素个数
将流中的数据转换成集合
List listA = streamA.collect(Collectors.toList());
Set setB = streamB.collect(Collectors.toSet());
package com.jxufe_ldl.class03;
import java.util.ArrayList;
import java.util.stream.Stream;
/*
现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作:
1:男演员只要名字为3个字的前三人
2:女演员只要姓林的,并且不要第一个
3:把过滤后的男演员姓名和女演员姓名合并到一起
4:把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
*/
public class Streamdemo06 {
public static void main(String[] args) {
//创建集合
ArrayList<String> manList = new ArrayList<String>();
manList.add("周润发");
manList.add("成龙");
manList.add("刘德华");
manList.add("吴京");
manList.add("周星驰");
manList.add("李连杰");
ArrayList<String> womanList = new ArrayList<String>();
womanList.add("林心如");
womanList.add("张曼玉");
womanList.add("林青霞");
womanList.add("柳岩");
womanList.add("林志玲");
womanList.add("王祖贤");
// 1:男演员只要名字为3个字的前三人
Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);
// 2:女演员只要姓林的,并且不要第一个
Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);
// 3:把过滤后的男演员姓名和女演员姓名合并到一起
Stream<String> concatStream = Stream.concat(manStream, womanStream);
// 4:把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
// concatStream.map(Actor::new).forEach(System.out::println);
concatStream.map(s -> new Actor(s)).forEach(System.out::println);
}
}
package com.jxufe_ldl.class03;
import java.util.ArrayList;
import java.util.List;
public class StreamDemo05 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("123");
list.add("223");
list.add("333");
list.add("444");
list.add("555");
// R apply(T t);
list.stream().map(s -> {
return Integer.parseInt(s);
}).forEach(System.out::println);
}
}
package com.jxufe_ldl.class03;
import java.util.ArrayList;
import java.util.List;
public class StreamDemo04 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("liuxiaoyu");
list.add("liudaliang");
list.add("yumanli");
list.add("liukun");
list.add("liuxiaoliang");
list.add("caixukun");
// 使用自然排序
list.stream().sorted().forEach(System.out::println);
System.out.println("---------");
// 排序规则为字符串的长度
list.stream().sorted((s1, s2) -> s1.length() - s2.length()).forEach(System.out::println);
System.out.println("---------");
// 长度相同则自然顺序排序
list.stream().sorted((s1, s2) -> {
int num = s1.length() - s2.length();
num = num == 0 ? s1.compareTo(s2) : num;
return num;
}).forEach(System.out::println);
}
}
package com.jxufe_ldl.class03;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
/*
注意:一个流只能被使用一次.
static Stream concat(Stream a, Stream b) : 是一个静态方法,需要传入两个Stream流对象,返回一个Stream对象
方法的作用: 把两个Stream流合并成一个Stream
Stream distinct() : 去重,把Stream流中重复元素去除一个.
*/
public class StreamDemo03 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("刘小鱼");
list.add("刘达亮");
list.add("于曼丽");
list.add("刘坤");
list.add("刘小亮");
list.add("蔡徐坤");
// 取集合的前4个元素
Stream<String> streamA = list.stream().limit(4);
// 跳过前两个元素,取集合后面的元素
Stream<String> streamB = list.stream().skip(2);
// 将两个流合并成一个流
Stream<String> streamC = Stream.concat(streamA, streamB);
// streamC.forEach(System.out::println);
// 将两个流合并成一个流,并去掉重复的元素
Stream<String> streamD = streamC.distinct();
streamD.forEach(System.out::println);
}
}
package com.jxufe_ldl.class03;
import java.util.ArrayList;
import java.util.List;
public class StreamDemo02 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("刘小鱼");
list.add("刘达亮");
list.add("于曼丽");
list.add("刘坤");
list.add("刘小亮");
list.add("蔡徐坤");
// 取前3个元素
list.stream().limit(3).forEach(System.out::println);
System.out.println("--------");
// 跳过前2个元素
list.stream().skip(2).forEach(System.out::println);
System.out.println("--------");
// 跳过前2个元素,再取前3个元素
list.stream().skip(2).limit(3).forEach(System.out::println);
}
}
package com.jxufe_ldl.class03;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
public class StreamDemo01 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("刘小鱼");
list.add("刘达亮");
list.add("于曼丽");
list.add("刘坤");
list.add("刘小亮");
// list.stream().filter(s->s.startsWith("刘")).filter(s->s.length() == 3).forEach(System.out::println);
list.stream().filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.startsWith("刘");
}
}).filter(new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() == 3;
}
}).forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
list.stream().filter((String s) -> {
return s.startsWith("刘");
}
).filter((String s) -> {
return s.length() == 3;
}
).forEach((String s) -> {
System.out.println(s);
}
);
}
}
package com.jxufe_ldl.class03;
/*
演员类
*/
public class Actor {
private String name;
public Actor(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Actor{" +
"name='" + name + '\'' +
'}';
}
}