public static void main(String[] args) {
/** * 3.流的终止操作 * 3.1 匹配和聚合操作 * allMatch:接收一个 Predicate 函数,当流中每个元素都符合该断言时才返回true,否则返回false * noneMatch:接收一个 Predicate 函数,当流中每个元素都不符合该断言时才返回true,否则返回false * anyMatch:接收一个 Predicate 函数,只要流中有一个元素满足该断言则返回true,否则返回false * findFirst:返回流中第一个元素 * findAny:返回流中的任意元素 * count:返回流中元素的总个数 * max:返回流中元素最大值 * min:返回流中元素最小值 * 3.2 归约操作 * Optional
reduce(BinaryOperator accumulator): * 第一次执行时,accumulator函数的第一个参数为流中的第一个元素,第二个参数为流中元素的第二个元素; * 第二次执行时,第一个参数为第一次函数执行的结果,第二个参数为流中的第三个元素;依次类推。 * T reduce(T identity, BinaryOperator accumulator): * 流程跟上面一样,只是第一次执行时,accumulator函数的第一个参数为identity,而第二个参数为流中的第一个元素。 * U reduce(U identity,BiFunction accumulator,BinaryOperator combiner): * 在串行流(stream)中,该方法跟第二个方法一样,即第三个参数combiner不会起作用。在并行流(parallelStream)中,我们知道流被fork join出多个线程进行执行,此时每个线程的执行流程就跟第二个方法reduce(identity,accumulator)一样,而第三个参数combiner函数,则是将每个线程的执行结果当成一个新的流,然后使用第一个方法reduce(accumulator)流程进行规约。
* 3.3 收集操作
* collect:接收一个Collector实例,将流中元素收集成另外一个数据结构。
* Collector是一个接口,有以下5个抽象方法:
* Supplier supplier():创建一个结果容器A
* BiConsumer accumulator():消费型接口,第一个参数为容器A,第二个参数为流中元素T。
* BinaryOperator combiner():函数接口,该参数的作用跟上一个方法(reduce)中的combiner参数一样,将并行流中各
个子进程的运行结果(accumulator函数操作后的容器A)进行合并。
* Function finisher():函数式接口,参数为:容器A,返回类型为:collect方法最终想要的结果R。
* Set characteristics():返回一个不可变的Set集合,用来表明该Collector的特征。有以下三个特征:
*
* CONCURRENT:表示此收集器支持并发。(官方文档还有其他描述,暂时没去探索,故不作过多翻译)
* UNORDERED:表示该收集操作不会保留流中元素原有的顺序。
* IDENTITY_FINISH:表示finisher参数只是标识而已,可忽略。
*/
List integers = Arrays.asList(1, 2, 6, 7, 9);
//必须每一个元素都符合该断言 断言是(c>10 就是断言 1=1 也叫断言 )
//false
System.out.println(integers.stream().allMatch(c -> c > 10));
//true
System.out.println(integers.stream().noneMatch(c -> c > 10));
//true
System.out.println(integers.stream().anyMatch(c -> c > 4));
//返回流中第一个元素
System.out.println(integers.stream().findFirst().get());
//返回流中的随机一个元素
System.out.println(integers.stream().findAny().get());
//获取流中的记录条数
System.out.println(integers.stream().count());
//最大值
System.out.println(integers.stream().max(Integer::compareTo).get());
//最小值 Integer::compareTo Integer compareTo 比较 等同下边这种写法
System.out.println(integers.stream().min(Integer::compareTo).get());
/**
* Integer::compareTo
* 等同于
* Integer s=1;
* s.compareTo(1);
* s.compareTo(1) 用于字符串和对象比较 或者两个值的比较
* return: 0 参数字符串等于当前参数字符串 返回值0
* return: -1 参数字符串小于当前参数字符串 返回值小于0的值
* return: 1 参数字符串大于当前参数字符串 返回值大于0的值
*
*/
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
/**
* Optional reduce(BinaryOperator accumulator):
* x1 y1
* 第一次执行时,accumulator函数的第一个参数为流中的第一个元素,第二个参数为流中元素的第二个元素;
* 看上边这句话 看完了
* 第二次执行时,第一个参数为第一次函数执行的结果,第二个参数为流中的第三个元素;依次类推。
* T reduce(T identity, BinaryOperator accumulator):
*
* 流程跟上面一样,只是第一次执行时,accumulator函数的第一个参数为identity,而第二个参数为流中的第一个元素。
*
* U reduce(U identity,BiFunction accumulator,BinaryOperator combiner):
* 在串行流(stream)中,该方法跟第二个方法一样,即第三个参数combiner不会起作用。在并行流(parallelStream)中,
* 我们知道流被fork join出多个线程进行执行,此时每个线程的执行流程就跟第二个方法reduce(identity,accumulator)一样,
* 而第三个参数combiner函数,则是将每个线程的执行结果当成一个新的流,然后使用第一个方法reduce(accumulator)流程进行规约。
*
*/
List bxStream = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
//这个要知道是啥 这是并行流内置forkjoin线程池 所以称为并行流 其效率是stream的数倍
bxStream.parallelStream();
//这一行说的是 这个集合整个结果相加 BinaryOperator(这个也是一个lambda表达式
//(a,b)->a+b x1代表当前第一个元素 x2代表第二个元素 x1, y1就代表这 整个stream流中的所有元素 x1+y1是对所有元素都执行这个操作
//此操作被称为归约 (可理解为归类约定)
//(x1, y1) -> x1 + y1 --------------------> 1+2+3+4+5+6+7+8+9+10
System.out.println("归约result:" + list.stream().reduce((x1, y1) -> x1 + y1).get());
//T identity 这个就是把 identity 当前元素为x1 其实集合的数据 应该是 10,1, 2, 3, 4, 5, 6, 7, 8, 9, 10
System.out.println(list.stream().reduce(10, (x1, y1) -> x1 + y1));
// List bxStream = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); 执行流程就是 0-1, 2, 3, 4, 5, 6, 7, 8, 9, 10
/**
* 定义是
* 在串行流(stream)中,该方法跟第二个方法一样,即第三个参数combiner不会起作用。
*
* 在并行流(parallelStream)中,
* 我们知道流被fork join出多个线程进行执行,此时每个线程的执行流程就跟第二个方法reduce(identity,accumulator)一样,
* 而第三个参数combiner函数,则是将每个线程的执行结果当成一个新的流,然后使用第一个方法reduce(accumulator)流程进行规约
* 0, (x1, x2) -> x1 * x2 ======================>这个最终结果执行为0 0乘以多少都是0呗 很简单
* 则是将每个线程的执行结果当成一个新的流 (重点就是这句话 它会把 [0, (x1, x2) -> x1 * x2 ] 这个的执行结果当成一个新的流去执行第三个)
* 新的流很明显只有一个数据就是0 0+0-0 都是0
*
* 总结:
* 串行流(Stream)
* reduce(T,accumulator,accumulator) 第三个函数式是不起作用的
* 并行流(parallelStream)
* reduce(T,accumulator,accumulator) 会先执行第二个函数式,然后把第二个函数试执行的结果当做一个新的流 去执行第三个函数式
*/
System.out.println("假设1:" + list.stream().reduce(0, (x1, x2) -> x1 - x2, (x1, x2) -> x1 * x2));
System.out.println("假设2:" + list.stream().reduce(0, (x1, x2) -> x1 * x2, (x1, x2) -> x1 - x2));
System.out.println("并行假设1:" + list.parallelStream().reduce(0, (x1, x2) -> x1 * x2, (x1, x2) -> x1 - x2));
System.out.println("规约结果集" + reduce);
//Collectors工具库
List students = new ArrayList();
students.add(new Student("aa", 10));
students.add(new Student("bb", 20));
students.add(new Student("cc", 30));
//获取年龄属性并转成List
/**
* public static
* Collector> toList() {
* return new CollectorImpl<>((Supplier>) ArrayList::new, List::add,
* (left, right) -> { left.addAll(right); return left; },
* CH_ID);
* }
* CH_ID:此处没啥用
* 创建一个新的arrayList 并add left,right 将当前的数据addAll 到一个新的list 并return
*
* static final Set CH_ID
* = Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH));
*
* 枚举类 了解就行
* CONCURRENT:表示此收集器支持并发。(官方文档还有其他描述,暂时没去探索,故不作过多翻译)
* UNORDERED:表示该收集操作不会保留流中元素原有的顺序。
* IDENTITY_FINISH:表示finisher参数只是标识而已,可忽略。
* */
students.stream().map(Student::getAge).collect(Collectors.toList()).forEach(System.out::println);
//获取年龄属性并转成Set
students.stream().map(Student::getAge).collect(Collectors.toSet()).forEach(System.out::println);
//获取当前学生并转成map 我想起来了Student::getName, Student::getAge)
Map<String, Integer> collect = students.stream().collect(HashMap::new, (m, v) -> m.put(v.getName(), v.getAge()), HashMap::putAll);
map遍历方式
collect.forEach((k, v) -> {
System.out.println("键" + k + "," + "值" + v);
});
//学生姓名分隔连接 都采用Collectors工具类 joining 分隔 Collectors.joining(",")
System.out.println(students.stream().map(Student::getName).collect(Collectors.joining(",")));
//计算学生年龄总和 这是一种 用Collectors工具类 Collectors.summingInt(Student::getAge))
//mapToInt这个啥意思 获取当前对象中的Int类型 最终返回一个Int流
//maptoint是intStream这个 intStream获取当前对象中的Int类型 最终返回一个Int流
//IntStream 其实是和 Stream类似的换个名字而已 单操作Integer类型 你发现其实方法都一样的 Int会有几个独有的方法相加等等
//Stream是流
IntStream intStream = students.stream().mapToInt(Student::getAge);
System.out.println(students.stream().collect(Collectors.summingInt(Student::getAge)));
//获取当前学生的最大年龄
System.out.println(students.stream()
.map(Student::getAge)
.collect(Collectors.toList())
.stream()
.max(Integer::compareTo).get());
//使用Collectors 工具类获取当前学生的最大年龄 Collectors.maxBy(Integer::compareTo)
System.out.println(students.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compareTo)).get());
//获取最小年龄 大的max小是min
System.out.println(students.stream().map(Student::getAge).collect(Collectors.minBy(Integer::compareTo)).get());
Integer integer = students.stream().map(Student::getAge).collect(Collectors.toList()).stream().min(Integer::compareTo).get();
//toList 是一个新的对象 新的List可以有Stream
//println 是 PrintStream类的非静态方法
/**
* System.out::println
* PrintStream out = System.out;
* Consumer fun2 = out::println;
* fun2.accept("hello");
* students.stream().forEach(System.out::println);
* (Student::getAge) (s->s.getAge()) Predicate->条件筛选
* 左边用于获取属性没办法去做.equals 等操作 适用于比较并可拼接(条件筛选 多用于过滤)
*
*/
//(Student::getAge)能实现的(s->s.getAge)它都能,但是(s->s.getAge)它能实现的(Student::getAge)他不能
//平均年龄 最后两 Collectors.averagingInt() averaging avg全称
System.out.println(students.stream().collect(Collectors.averagingInt(Student::getAge)));
//分组
students.stream().collect(Collectors.groupingBy(Student::getAge)).forEach((k, v) -> {
System.out.println("k" + k + "v" + v);
});
}