【Java】【基础知识】【函数编程】
【Java】【基础知识】【函数编程】
实践是检验真理的唯一方式
一、函数式接口
函数式接口特征:
1.只有一个抽象接口(没有和超过一个都不行)
2.可以有默认和静态方法
3.Object里的方法不算进去,比如equals等等
@FunctionalInterface 这个可以校验是否是函数式接口
1.Consumer
1.1、示意
消费者
代表了接受一个输入参数并且无返回的操作
void accept(T t);

1.2、接口讲解和示例
String t ="ss";
Consumer<String> con = System.out::println;
Consumer<String> con1 = string->System.out.println(string+"ddd");
con.accept(t);//执行con里的代码
con.andThen(con1).accept(t);//先执行con里的代码,再执行con2里的代码
1.3、应用
流 forEach
1.4、类似接口
传两个参数的:BiConsumer<T t,U u>
1.4.1、BiConsumer
String t ="ss";
String v ="vv";
BiConsumer<String,String> con = (a,b)->System.out.println(a+b);
BiConsumer<String,String> con1 = (a,b)->System.out.println(a+b+"dddd");
con.accept(t,v);//执行con里的代码
con.andThen(con1).accept(t,v);//先执行con里的代码,再执行con2里的代码

2、Predicate
2.1、示意
接受一个输入参数,返回一个布尔值结果。
boolean test(T t);

2.2、接口讲解和示例
String t ="ss";
Predicate<String> fun1 = string->string.equals("string");
Predicate<String> fun2 = string->string.equals("equals");
boolean bool = fun1.test(t);//test
boolean bool1 = fun1.and(fun2).test(t);//与
boolean bool2 = fun1.or(fun2).test(t);//或
boolean bool3 = fun1.negate().test(t);//非
boolean bool4 = Predicate.isEqual(v).test(t);//判断两个参数是否相等
2.3、应用
filter | allMatch | anyMatch | noneMatch
2.4、类似接口
三个基本类型的: DoublePredicate IntPredicate LongPredicate
传两个参数的:BiPredicate<T t,U u>
2.4.1、BiPredicate
String t ="ss";
String v ="sss";
BiPredicate<String,String> bi = (a,b)->a.length()>b.length();
BiPredicate<String,String> bi1 = (a,b)->a.equals(b);
boolean bool = bi.test(t,v);
boolean bool1 = bi.and(bi1).test(t,v);
boolean bool2 = bi.or(bi1).test(t,v);
boolean bool3 = bi.negate().test(t,v);

3、Function
3.1、示意
接受一个输入参数,返回一个结果。
抽象方法:R apply(T t);

3.2、接口讲解与示例:
/**
* FUnction apply
* @param value
* @param function
* @return
*/
public static Integer testFunction(Integer value, Function<Integer,Integer> function){
return function.apply(value);
}
/**
* Function compose
* @param value
* @param fun1
* @param fun2
* @return
*/
public static Integer testFunction1(Integer value,Function<Integer,Integer> fun1,Function<Integer,Integer>fun2){
/**
* compose的返回值是一个Function接口的实例化,
* 先执行fun2,然后将处理好的值再放入fun1里,最后返回处理结果
*/
return fun1.compose(fun2).apply(value);
}
/**
* Function andThen
* @param value
* @param fun1
* @param fun2
* @return
*/
public static Integer testFunction2(Integer value,Function<Integer,Integer>fun1,Function<Integer,Integer>fun2){
/**
* andTHen与compose正好相反,先执行fun1,再将处理的值放入fun2中,最后返回处理结果
*/
return fun1.andThen(fun2).apply(value);
}
3.3、应用
流的 map flatMap
3.4、类似接口
三个基本类型的: DoubleFunction IntFunction LongFunction
传两个参数的:BiFunction<T t,U u>
3.4.1、BiFunction的使用
/**
* BiFUnction apply
* @param v1
* @param v2
* @param fun1
* @return
*/
public static Integer testFunction3(Integer v1, Integer v2, BiFunction<Integer, Integer, Integer> fun1) {
return fun1.apply(v1, v2);
}
/**
* BiFUnction andThen
* @param v1
* @param v2
* @param fun1
* @param fun2
* @return
*/
public static Integer testFunction4(Integer v1, Integer v2, BiFunction<Integer, Integer, Integer> fun1, Function<Integer, Integer> fun2) {
/**
* 先执行fun1,然后将处理的值传入fun2,最终返回结果
* andThen的入参是一个FUnction函数接口实例
*/
return fun1.andThen(fun2).apply(v1,v2);
}

4、Supplier
4.1、示意
提供初始值
无参数,返回一个结果。
T get();
4.2、接口讲解与示例
4.3、应用
4.4、类似接口
5、BinaryOperator
5.1、示意
BinaryOperator继承了BiFunction,是BiFunction的一种特殊情况,两个参数和返回值都是同一个类型
相比于BIFUnction,还多了两个筛选最大值和最小值的方法
T apply(T t, T v);

5.2、接口解释与实例
BinaryOperator<Integer> binaryOperator = (integer, integer2) -> {
return integer2-integer;
};
System.out.println(binaryOperator.apply(3,6));
Comparator<Integer> comparator = Comparator.comparing(Integer::intValue);
Integer i1 = BinaryOperator.maxBy(comparator).apply(3, 6);
Integer i2 = BinaryOperator.minBy(comparator).apply(3, 6);
System.out.println(i1);
5.3、应用
流 reduce
5.4、类似接口
6、Comparator
6.1、示意
int compare(T o1, T o2);

6.2、接口解释与示例
基本类型的比较:
Comparator<Integer> comparator = (a,b)->a-b;//1
Comparator<Integer> comparator = Comparator.comparing(Integer::intValue);//2
Comparator<Integer> comparator = Integer::compareTo;//3
引用类型比较
Student stu1 = new Student("qq",12);
Student stu2 = new Student("qq",12);
Comparator<Student> comparator = (a,b)->a.getAge()-b.getAge();//1
Comparator<Student> comparator = Comparator.comparing(Student::getAge);//2
System.out.println(comparator.compare(stu1,stu2));
6.3、应用
流 sorted max min
二、匿名内部类
1.结构
new 实现接口() | 父类构造器(实参列表){
//匿名内部类的类体部分
}
三、Lambda表达式
1.结构
(参数类型 变量名 ,参数类型 变量名)->
{
//方法体
}
2.作用域
可以访问类变量、成员变量和局部变量,根据使用,受限不一
3.注意点
(Integer first,Integer second)->{ return first-second}
参数可以省略参数类型
(first,second)->{ return first-second}
只有一个参数,可以省略括号
first->{Systen.out.prinln(first)}
只有一条语句,可以省略return关键字和花括号
(first,second)->first-second
四、方法引用
1.结构
object::instanceMethod 实例引用 instanceMethod 实例方法
Class::staticMethod 静态引用 staticMethod 静态方法
Class::instanceMethod
String[] arr = new String[] { "aa", "aaq", "wer" };
List<GoodStudent> test = Arrays.stream(arr).map(GoodStudent::new).collect(Collectors.toList());
test.forEach(a->System.out::println);
五、流
5.1.stream分类
Stream,IntStream,LongStream,DoubleStream
在传入三种基本数据类型的数组时,会自动使用相应的流,比如IntStream,虽然都是流,但是里面的方法还是有所差异,比如sorted,在IntStream只支持默认的自然排序,不支持自定义排序。
5.2.创建流的几种方式
1.通过Collection接口创建
继承Collection的集合都可以创建流
default Stream<E> stream():返回一个顺序流
default Stream<E> parallelStream():返回一个并行流
2.通过Arrays静态方法stream()创建数组流
数组创建流,但只支持int double long三种基本类型数组 + 引用类型数组
static <T> Stream<T> stream(T[] array):返回一个T类型的数组流
public static IntStream stream(int[] array):返回一个int型的数组流
public static LongStream stream(long[] array):返回一个long类型的数组流
public static DoubleStream stream(double[] array):返回一个double类型的数组流
3.Stream的内置方法
值/T t 即可以填写数组
public static <T>Stream <T> of(T... values):接收任意数量的参数返回一个T类型的流
迭代方式:
public static <T> Stream<T>iterate(final T seed,final UnaryOperator<T>f)
生成方式:
public static <T>Stream <T>generate(Supplier<T> s):
Integer[] intArr = new Integer[] {1,2,3,45,6};
System.out.println(Stream.of(intArr).collect(Collectors.counting()));
5.3、流操作
5.3.1、中间操作
方法 | 描述 |
---|---|
filter(Predicate p) | 过滤操作 |
map(Function f) | 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新元素 |
flatMap(Function f) | 接收一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连接成一个流 |
sorted(Comparator comp) | 产生一个新流,按照比较器排序 |
distinct() | 去重,通过流生成元素的hashCode()和equals()方法去除重复元素 |
limit(long maxSize) | 截断流,使元素不超过给定的数量 |
skip(long n) | 跳过指定数量的元素 |
mapToDouble(ToDoubleFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的DoubleStream |
mapToInt(ToIntFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的IntStream |
mapToLong(ToLongFunction f) | 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的LongStream |
5.3.2、终止操作(终端操作)
方法 | 操作 |
---|---|
count() | 返回流中元素总数 |
forEach(Consumer c) | 内部迭代使用Collection接口需要用户去迭代,称为内部迭代,相反,StreamApi使用内部迭代--StreamAPI帮你把迭代做了 |
reduce(T,iden,BinaryOperator b) | 第一个参数是初始值 |
reduce(BinaryOperator b) | 可以将流中的元素反结合起来得到一个值。返回 Optional |
collect(Collector c) | 将流转换为其它形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最下值 |
findFirst() | 返回第一个元素 |
findAny() | 返回流中任意的元素 |
allMatch(Predicate p) | 检查是否匹配所有元素 |
anyMatch(Predicate p) | 检查是否至少匹配一个元素 |
noneMatch(Predicate p) | 检查是否没有匹配所有元素 |
*Collector接口 Collectors实现类(collect)
方法 | 返回类型 | 作用 | 示例 |
---|---|---|---|
reducing | 归约产生的类型 | 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值 | int total=list.stream().collect(Collectors.reducing(0,Employee::getSalar,Integer::sum) |
partitioningBy | Map<Boolean,List |
根据true或false进行分区 | Map<Boolean,List |
groupingBy | Map<K, List |
根据某属性值对流分组,属性为K,结果为V | Map<Emp.Status, List |
collectingAndThen | 转换函数返回的类型 | 包裹另一个收集器,对其结果转换函数 | int how= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(),List::size)); |
toList | List |
||
toSet | Set |
把流中元素收集到Set | Set |
toCollection | Collection |
把流中元素收集到创建的集合 | Collection |
counting | Long | 计算流中元素的个数 | long count = list.stream().collect(Collectors.counting()); |
joinin | String | 连接流中每个字符串 | String str= list.stream().map(Employee::getName).collect(Collectors.joining()); |
summingInt | Integer | 对流中元素的整数属性求和 | int total=list.stream().collect(Collectors.summingInt(Employee::getSalary); |
maxBy | Optional |
根据比较器选择最大值 | Optional |
minBy | Optional |
根据比较器选择最小值 | Optional |
averagingInt | Double | 计算流中元素Integer属性的平均值 | double avg= list.stream().collect(Collectors.averagingInt(Employee::getSalary)); |
summarizingInt | IntSummaryStatistics | 收集流中Integer属性的统计值。如:平均值 | IntSummaryStatisticsis s= list.stream().collect(Collectors.summarizingInt(Employee::getSalary)); |
// groupingBy 根据返回值分类,一种返回值,一组 支持多条件分组
//需要在你创建的类里创建一个静态变量count,初始值为0
Integer[] intArr = new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
Map<Boolean, Map<Boolean, List<Integer>>> map = Arrays.stream(intArr)
.collect(Collectors.groupingBy(a -> a % 2 == 0, Collectors.groupingBy(a -> a % 3 == 0)));
map.entrySet().forEach(entry -> {
System.out.println("\n");
System.out.println("父类执行:");
entry.getValue().entrySet().forEach(e -> {
System.out.println("-----子类执行" + count);
e.getValue().stream().forEach(System.out::println);
count++;
});
});
//collectingAndThen 先 Collector ,再 Function; 注意:Function是对 Collector操作后的整体stream做操作
//先执行了groupingBy,返回了map,然后输出了map的长度
Integer[] intArr = new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
System.out.println(Arrays.stream(intArr).collect(Collectors.collectingAndThen(Collectors.groupingBy(a->a%2==0),map->map.size() )));
本文来自博客园,作者:时光与简,转载请注明原文链接:https://www.cnblogs.com/simpletime/p/16745746.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)