【Java】【基础知识】【函数编程】

实践是检验真理的唯一方式

一、函数式接口

函数式接口特征:
	1.只有一个抽象接口(没有和超过一个都不行)
	2.可以有默认和静态方法
	3.Object里的方法不算进去,比如equals等等
@FunctionalInterface 这个可以校验是否是函数式接口

1.Consumer

1.1、示意
消费者
代表了接受一个输入参数并且无返回的操作
void accept(T t);


java 设置const类成员 java const函数_java 设置const类成员

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里的代码


java 设置const类成员 java const函数_java_02

2、Predicate

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


java 设置const类成员 java const函数_java_03

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);


java 设置const类成员 java const函数_System_04

3、Function

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


java 设置const类成员 java const函数_数组_05

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);
}


java 设置const类成员 java const函数_java_06

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);


java 设置const类成员 java const函数_List_07

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);


java 设置const类成员 java const函数_java_08

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>vd= list.stream().collect(Collectors.partitioningBy(Employee::getManage));

groupingBy

Map<K, List>

根据某属性值对流分组,属性为K,结果为V

Map<Emp.Status, List> map= list.stream().collect(Collectors.groupingBy(Employee::getStatus))

collectingAndThen

转换函数返回的类型

包裹另一个收集器,对其结果转换函数

int how= list.stream().collect(Collectors.collectingAndThen(Collectors.toList(),List::size));

toList

List

toSet

Set

把流中元素收集到Set

Set emps= list.stream().collect(Collectors.toSet());

toCollection

Collection

把流中元素收集到创建的集合

Collectionemps=list.stream().collect(Collectiors.toCollection(ArrayList::new));

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

根据比较器选择最大值

Optionalmax= list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));

minBy

Optional

根据比较器选择最小值

Optional min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));

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() )));