文章目录
函数式接口
函数式接口概述
- 概念
有且仅有一个抽象方法的接口 - 如何检测一个接口是不是函数式接口
@FunctionalInterface
放在接口定义的上方:如果接口是函数式接口,编译通过;如果不是,编译失败 - 注意事项
我们自己定义函数式接口的时候,@FunctionalInterface是可选的,就算我不写这个注解,只要保证满足函数式接口定义的条件,也照样是函数式接口。但是,建议加上该注解
- 函数式接口可以作为方法的参数 //也就是用lambda表达式作为参数,下方同理
- 函数式接口可以作为方法的返回值
函数式接口Supplier
Supplier
接口
Supplier接口也被称为生产型接口
,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产
什么类型的数据供我们使用。
方法名 | 说明 |
---|---|
T get() | 按照某种实现逻辑(由Lambda表达式实现)返回一个数据 |
import java.util.function.Supplier;
public class example_2 {
public static void main(String[] args) {
String s = show(() -> {
return "hello";
});
System.out.println(s);
}
private static String show(Supplier<String> supplier) {
return supplier.get();
}
}
函数式接口Consumer
Consumer
接口
Consumer
接口也被称为消费型接口
,它消费的数据的数据类型由泛型指定
方法名 | 说明 |
---|---|
void accept(T t) | 对给定的参数执行此操作 |
default Consumer andThen(Consumer after) | 返回一个组合的Consumer,依次执行此操作,然后执行after操作 |
import java.util.function.Consumer;
public class example_4 {
public static void main(String[] args) {
operatorString("Java", s -> {
StringBuilder reverse = new StringBuilder(s).reverse(); //将字符串翻转
System.out.println(reverse);
});
}
private static void operatorString(String name, Consumer<String> consumer) {
consumer.accept(name);
}
}
使用方法andThen()方法需要两个参数
例如
con1.andThen(con2).accept(name);
意思就是操作完1后再操作2
函数式接口Predicate
Predicate
接口
Predicate
接口通常用于判断参数是否满足指定的条件
方法名 | 说明 |
---|---|
boolean test(T t) | 对给定的参数进行判断 (判断逻辑由Lambda表达式实现),返回一个布尔值 |
default Predicate negate() | 返回一个逻辑的否定 ,对应逻辑非 |
default Predicate and(Predicate other) | 返回一个组合判断,对应短路与 |
default Predicate or(Predicate other) | 返回一个组合判断,对应短路或 |
import java.util.function.Predicate;
public class example_5 {
public static void main(String[] args) {
boolean b = checkString("hello", s -> {
return s.length() > 88;
});
System.out.println(b);
}
private static boolean checkString(String s, Predicate<String> predicate) {
return predicate.negate().test(s); //由于进行了negate操作所以就为true
}
}
函数式接口Function
Function
接口
Function<T,R>
接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值
方法名 | 说明 |
---|---|
R apply (T t) | 将此函数应用于给定的参数default Function |
andThen(Function after) | 返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果 |
将字符串类型转为int类型
import java.util.function.Function;
public class example_6 {
public static void main(String[] args) {
convert("711" , s -> { //myBirthday:)
return Integer.parseInt(s);
});
}
private static void convert(String s, Function<String,Integer> function) {
Integer apply = function.apply(s);
System.out.println(apply);
}
}
Stream流
- Stream流的好处
- 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义
- Stream流把真正的函数式编程风格引入到Java中
先看一个例子
import java.util.ArrayList;
public class example_7 {
public static void main(String[] args) {
ArrayList<String> studentList = new ArrayList<String>();
studentList.add("梁小敏");
studentList.add("许三多");
studentList.add("梁非凡");
studentList.add("刘松");
studentList.add("梁飞");
//不使用Stream流的代码量:
System.out.println("不使用Stream流:");
ArrayList<String> arrayList = new ArrayList<>();
for (String s :
studentList) {
if (s.startsWith("梁")) { //过滤姓梁的学生
arrayList.add(s);
}
}
ArrayList<String> arrayList2 = new ArrayList<>();
for (String s :
arrayList) {
if (s.length() == 3) { //只要名字长度为3的
arrayList2.add(s);
}
}
for (String s :
arrayList2) { //遍历
System.out.println(s);
}
//使用Stream流的代码量:
System.out.println("使用stream流");
studentList.stream().filter(s -> s.startsWith("梁")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));
}
}
从例子看出使用Stream流可以使代码量大大减少,接下来是对Stream流的具体介绍和使用
Stream流的常见生成方式
- 生成Stream流的方式
Collection体系集合
//也就是List
和Set
使用默认方法stream()生成流, default Stream stream()- Map体系集合
把Map转成Set集合,间接的生成流 //通过方法将Map转为Set - 数组
通过Stream接口的静态方法of(T… values)生成流
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;
public class example_1 {
public static void main(String[] args) {
//Collection体系的集合可以使用stream()方法生成流
ArrayList<String> arrayList = new ArrayList<>();
Stream<String> stream = arrayList.stream();
HashSet<String> hashSet = new HashSet<>();
Stream<String> stringStream = hashSet.stream();
//Map体系间接生成
HashMap<String, Integer> hashMap = new HashMap<>();
Set<String> keySet = hashMap.keySet();
Stream<String> stringStream1 = keySet.stream(); //间接生成
//数组
String[] strArray = {"hello","hi","Java"};
Stream<String> strArray1 = Stream.of(strArray); //接口调用静态方法生成
Stream<String> stringStream2 = Stream.of("10", "20", "30"); //通过数组的可变参数生成
}
}
Stream流中间操作方法
- 概念
中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作。
方法名 | 说明 |
---|---|
Stream filter (Predicate predicate) | 用于对流中的数据进行过滤 |
Stream limit (long maxSize) | 返回此流中的元素组成的流,截取前 指定参数个数的数据 |
Stream skip (long n) | 跳过指定参数 个数的数据,返回由该流的剩余元素组成的流 |
static Stream concat (Stream a, Stream b) | 合并 a和b两个流为一个流 |
Stream distinct() | 返回由该流的不同元素(根据Object.equals(Object) )组成的流 |
Stream sorted () | 返回由此流的元素组成的流,根据自然顺序排序 |
Stream sorted(Comparator comparator) | 返回由该流的元素组成的流,根据提供的Comparator进行排序 |
Stream map (Function mapper) | 返回由给定函数应用于此流的元素的结果组成的流 |
IntStream mapToInt (ToIntFunction mapper) | 返回一个IntStream其中包含将给定函数应用于此流的元素的结果 |
上述方法也就是其参数是一个lambda表达式进行相关的操作
ps: mapToInt()方法
里面可以调用sum()方法
对整形集合进行求和操作
Stream流终结操作方法
- 概念
终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作。
方法名 | 说明 |
---|---|
void for each (Consumer action) | 对此流的每个元素执行操作 //用得较多 |
long count() | 返回此流中的元素数 |
ps : 总而言之使用Stream
流的目的就是使代码更加简单明了,开发的效率提高
CET4P232
- crust
- insight
- guideline
- fireman
- junior
- observation
- whale
- nuclear
- brand
- mention
- whatever
- relax