【Java】【基础知识】【函数式接口与Stream流】

【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)
partitioningByMap<Boolean,List>根据true或false进行分区Map<Boolean,List>vd= list.stream().collect(Collectors.partitioningBy(Employee::getManage));
groupingByMap<K, List>根据某属性值对流分组,属性为K,结果为VMap<Emp.Status, List> map= list.stream().collect(Collectors.groupingBy(Employee::getStatus))
collectingAndThen转换函数返回的类型包裹另一个收集器,对其结果转换函数int how= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(),List::size));
toListList
toSetSet把流中元素收集到SetSet emps= list.stream().collect(Collectors.toSet());
toCollectionCollection把流中元素收集到创建的集合Collectionemps=list.stream().collect(Collectiors.toCollection(ArrayList::new));
countingLong计算流中元素的个数long count = list.stream().collect(Collectors.counting());
joininString连接流中每个字符串String str= list.stream().map(Employee::getName).collect(Collectors.joining());
summingIntInteger对流中元素的整数属性求和int total=list.stream().collect(Collectors.summingInt(Employee::getSalary);
maxByOptional根据比较器选择最大值Optionalmax= list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
minByOptional根据比较器选择最小值Optional min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));
averagingIntDouble计算流中元素Integer属性的平均值double avg= list.stream().collect(Collectors.averagingInt(Employee::getSalary));
summarizingIntIntSummaryStatistics收集流中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() )));
	


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值