文章目录
创建Stream的几种方式中间操作筛选与切片filter:可以使用Lambda,从Stream中排除某些元素limit:截断流,使其元素不超过给定数量,超过给定数量的数据,不再继续执行skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素map:将元素转换成其他形式提取信息,接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所以的流连接成一个流sorted():自然排序(Comparable)sorted(Comparator comparator):定制排序(Comparator)
查找与匹配allMatch:检查是否匹配所有元素anyMatch:检查是否至少匹配一个元素noneMatch:检查是否没有匹配所有元素findFirst:返回第一个元素findAny:返回当前流中的任意元素count:返回流中元素的总个数max:返回流中的最大值min:返回流中的最小值
终止操作归约和收集reduce:可以将流中的元素反复结合起来,得到一个值collect:将流转换为其他数据类型格式,接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
并行流与串行流串行流:Stream上的操作是在一个线程中依次完成并行流:Stream上的操作是在多个线程上同时执行
了解Fork/Join框架Fork/Join框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join汇总。
Fork/Join框架与传统线程池的区别采用工作窃取模式(work-stealing):
创建Stream的几种方式
1.通过Collection集合提供的stream()(串行流),parallelStream()(并行流)
List<String> list = new ArrayList<>();
Stream<String> str = list.stream();
2.通过Arrays.stream,获取数组流
Person[] employees = new Person[10];
Stream<String> stream1 = list.stream(Person);
3.通过Stream类中的静态方法 of()
Stream<String> aa = Stream.of("aa", "bb", "cc");
4.创建无限流
//第一种迭代
Stream<Integer> iterate = Stream.iterate(0, (x) -> x = 2);
iterate.limit(10).forEach(System.out::println);
//第二种迭代
Stream.generate(()->Math.random())
.limit(5)
.forEach(System.out::println);
中间操作
筛选与切片
filter:可以使用Lambda,从Stream中排除某些元素
package com.example.learnlambda.test;
import com.example.learnlambda.entity.Person;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Person> personArrayList = new ArrayList<>();
personArrayList.add(new Person(1, "张三", 89, 342.5));
personArrayList.add(new Person(2, "李四", 66, 678.2));
personArrayList.add(new Person(3, "王五", 27, 426.5));
personArrayList.add(new Person(4, "任六", 19, 793.5));
personArrayList.add(new Person(5, "田七", 33, 823.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
/*
多个中间操作可以连接起来形成一个流水线。
除非流水线上触发终止操作,否则中间操作不会执行任何的处理!
而在终止操作时一次性全部处理
*/
personArrayList
.stream()
// filter:中间操作。可以使用Lambda,从Stream中排除某些元素
// 如果没有终止操作,中间操作(filter)不执行
.filter((person) -> {
System.out.println("Stream API 的中间操作");
return person.getAge() <= 20;
})
//终止操作
.forEach(System.out::println);
}
}
limit:截断流,使其元素不超过给定数量,超过给定数量的数据,不再继续执行
package com.example.learnlambda.test;
import com.example.learnlambda.entity.Person;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Person> personArrayList = new ArrayList<>();
personArrayList.add(new Person(1, "张三", 89, 342.5));
personArrayList.add(new Person(2, "李四", 66, 678.2));
personArrayList.add(new Person(3, "王五", 27, 426.5));
personArrayList.add(new Person(4, "任六", 19, 793.5));
personArrayList.add(new Person(5, "田七", 33, 823.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
/*
多个中间操作可以连接起来形成一个流水线。
除非流水线上触发终止操作,否则中间操作不会执行任何的处理!
而在终止操作时一次性全部处理
*/
personArrayList
.stream()
// filter:中间操作。可以使用Lambda,从Stream中排除某些元素
// 如果没有终止操作,中间操作(filter)不执行
.filter((person) -> {
System.out.println("短路!");
return person.getAge() >= 20;
})
// 使其元素不超过给定的数量,超过给定数量的数据,不再继续执行
.limit(2)
//终止操作
.forEach(System.out::println);
}
}
skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
package com.example.learnlambda.test;
import com.example.learnlambda.entity.Person;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Person> personArrayList = new ArrayList<>();
personArrayList.add(new Person(1, "张三", 89, 342.5));
personArrayList.add(new Person(2, "李四", 66, 678.2));
personArrayList.add(new Person(3, "王五", 27, 426.5));
personArrayList.add(new Person(4, "任六", 19, 793.5));
personArrayList.add(new Person(5, "田七", 33, 823.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList
.stream()
// filter:中间操作。可以使用Lambda,从Stream中排除某些元素
// 如果没有终止操作,中间操作(filter)不执行
.filter((person) -> person.getAge() > 10)
// 跳过n元素前的元素(包括n元素)
// 如果此元素前的不足n个,返回一个空流
.skip(3)
//终止操作
.forEach(System.out::println);
}
}
distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素
package com.example.learnlambda.test;
import com.example.learnlambda.entity.Person;
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<Person> personArrayList = new ArrayList<>();
personArrayList.add(new Person(1, "张三", 87, 342.5));
personArrayList.add(new Person(2, "李四", 66, 678.2));
personArrayList.add(new Person(3, "王五", 27, 426.5));
personArrayList.add(new Person(4, "任六", 19, 793.5));
personArrayList.add(new Person(5, "田七", 33, 823.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList
.stream()
// filter:中间操作。可以使用Lambda,从Stream中排除某些元素
// 如果没有终止操作,中间操作(filter)不执行
.filter((person) -> person.getAge() > 10)
// 跳过n元素前的元素(包括n元素)
// 如果此元素前的不足n个,返回一个空流
.skip(2)
//去重操作,需要重写hashCode和equals
.distinct()
//终止操作
.forEach(System.out::println);
}
}
map:将元素转换成其他形式提取信息,接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所以的流连接成一个流
package com.example.learnlambda.test;
import com.example.learnlambda.entity.Person;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class Test {
public static void main(String[] args) {
ArrayList<Person> personArrayList = new ArrayList<>();
personArrayList.add(new Person(1, "张三", 87, 342.5));
personArrayList.add(new Person(2, "李四", 66, 678.2));
personArrayList.add(new Person(3, "王五", 27, 426.5));
personArrayList.add(new Person(4, "任六", 19, 793.5));
personArrayList.add(new Person(5, "田七", 33, 823.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
// map:将元素转换成其他形式提取信息,接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
// flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所以的流连接成一个流
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");
// map:接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
list.stream()
// 提取aaa应用到str函数上,然后提取bbb应用到str函数上
.map((str) -> str.toUpperCase())
.forEach(System.out::println);
// 输出:AAA BBB CCC DDD
System.out.print("============================================");
// flatMap:将流中的每个值都换成另一个流,然后把所以的流连接成一个流
list.stream()
// Test:类
// filterCharacter:类中的方法
.flatMap(Test::filterCharacter)
.forEach(System.out::println);
}
public static Stream<Character> filterCharacter(String str){
ArrayList<Character> arrayList = new ArrayList<>();
for (Character character : str.toCharArray()) {
arrayList.add(character);
}
return arrayList.stream();
}
}
sorted():自然排序(Comparable)
sorted(Comparator comparator):定制排序(Comparator)
package com.example.learnlambda.test;
import com.example.learnlambda.entity.Person;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test {
public static void main(String[] args) {
//sorted():自然排序(Comparable)
List<String> list = Arrays.asList("aaa", "eee", "ccc", "ddd", "bbb");
list.stream()
.sorted()
.forEach(System.out::println);
//输出结果:aaa bbb ccc ddd eee
System.out.println(" ================ 分割线 =============== ");
//sorted(Comparator comparator):定制排序(Comparator)
List<Person> personArrayList = new ArrayList<>();
personArrayList.add(new Person(1, "张三", 87, 342.5));
personArrayList.add(new Person(2, "李四", 66, 678.2));
personArrayList.add(new Person(3, "王五", 27, 426.5));
personArrayList.add(new Person(4, "任六", 19, 532.5));
personArrayList.add(new Person(5, "田七", 33, 823.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.stream()
.sorted((person1, person2) -> {
//根据年龄(age)排序,再根据工资(salary)排序
if (person1.getAge().equals(person2.getAge())) {
return person1.getSalary().compareTo(person2.getSalary());
} else {
return person1.getAge().compareTo(person2.getAge());
}
}).forEach(System.out::println);
/*
* 输出结果:Person{id=4, name='任六', age=19, salary=532.5}
Person{id=6, name='王八', age=21, salary=532.5}
Person{id=6, name='王八', age=21, salary=532.5}
Person{id=6, name='王八', age=21, salary=532.5}
Person{id=3, name='王五', age=27, salary=426.5}
Person{id=5, name='田七', age=33, salary=823.5}
Person{id=2, name='李四', age=66, salary=678.2}
Person{id=1, name='张三', age=87, salary=342.5}
*
* */
}
}
查找与匹配
allMatch:检查是否匹配所有元素
anyMatch:检查是否至少匹配一个元素
noneMatch:检查是否没有匹配所有元素
findFirst:返回第一个元素
findAny:返回当前流中的任意元素
count:返回流中元素的总个数
max:返回流中的最大值
min:返回流中的最小值
package com.example.learnlambda.test;
import com.example.learnlambda.entity.Person;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class TestFind {
public static void main(String[] args) {
List<Person> personArrayList = new ArrayList<>();
personArrayList.add(new Person(1, "张三", 27, 342.5));
personArrayList.add(new Person(2, "李四", 66, 678.2));
personArrayList.add(new Person(3, "王五", 27, 426.5));
personArrayList.add(new Person(4, "任六", 19, 532.5));
personArrayList.add(new Person(5, "田七", 33, 823.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
//allMatch:检查是否匹配所有元素
boolean ballMatch = personArrayList.stream()
.allMatch((person) -> person.getSalary().equals(532.5));
System.out.println("ballMatch = " + ballMatch); //false
//anyMatch:检查是否至少匹配一个元素
boolean banyMatch = personArrayList.stream()
.anyMatch((person) -> person.getSalary().equals(532.5));
System.out.println("banyMatch = " + banyMatch); //true
//noneMatch;检查是否没有匹配所以元素
boolean bnoneMatch = personArrayList.stream()
.noneMatch((person) -> person.getSalary().equals(532.5));
System.out.println("bnoneMatch = " + bnoneMatch);
//findFirst:返回第一个元素
Optional<Person> findFirst = personArrayList.stream()
.sorted((person1, person2) -> Double.compare(person1.getSalary(), person2.getSalary()))
.findFirst();
System.out.println("findFirst = " + findFirst);
//findAny:返回当前流中的任意元素
Optional<Person> findAny = personArrayList.stream()
.filter((person) -> person.getAge().equals(27))
.findAny();
System.out.println("findAny = " + findAny.get());
//count:返回流中元素的总个数
long count = personArrayList.stream()
.count();
System.out.println("count = " + count);
//max:返回流中的最大值
//第一种写法
Optional<Person> max = personArrayList.stream()
.max((person1, person2) -> Double.compare(person1.getSalary(), person2.getSalary()));
System.out.println("max = " + max.get());
//第二种写法
Optional<Double> maxDouble = personArrayList.stream()
.map(Person::getSalary)
.max(Double::compareTo);
System.out.println("maxDouble.get() = " + maxDouble.get());
//min:返回流中的最小值
//第一种写法
Optional<Person> min = personArrayList.stream()
.min((person1, person2) -> Double.compare(person1.getSalary(), person2.getSalary()));
System.out.println("min = " + min.get());
//第二种写法
Optional<Double> minDouble = personArrayList.stream()
.map(Person::getSalary)
.min(Double::compareTo);
System.out.println("minDouble = " + minDouble);
}
}
终止操作
归约和收集
reduce:可以将流中的元素反复结合起来,得到一个值
collect:将流转换为其他数据类型格式,接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
package com.example.learnlambda.test;
import com.example.learnlambda.entity.Person;
import java.util.*;
import java.util.stream.Collectors;
public class TestReduce {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9,10);
//reduce 简单归约
Integer reduce = list.stream()
.reduce(0, (x, y) -> x + y);
System.out.println("reduce = " + reduce);
List<Person> personArrayList = new ArrayList<>();
personArrayList.add(new Person(1, "张三", 27, 342.5));
personArrayList.add(new Person(2, "李四", 66, 678.2));
personArrayList.add(new Person(3, "王五", 27, 426.5));
personArrayList.add(new Person(4, "任六", 19, 532.5));
personArrayList.add(new Person(5, "田七", 33, 823.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
personArrayList.add(new Person(6, "王八", 21, 532.5));
//map-reduce归约
Optional<Double> reduceDouble = personArrayList.stream()
.map(Person::getSalary)
.reduce(Double::sum);
System.out.println("reduceDouble = " + reduceDouble);
//collect:收集,将流转换为其他数据类型格式,接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
//收集所有姓名到list中
List<String> listCollect = personArrayList.stream()
.map(Person::getName)
.collect(Collectors.toList());
System.out.println("listCollect = " + listCollect);
//收集所有姓名到set中
Set<String> setCollect = personArrayList.stream()
.map(Person::getName)
.collect(Collectors.toSet());
System.out.println("setCollect = " + setCollect);
//收集所有姓名到Hashset中
HashSet<String> hashSetCollect = personArrayList.stream()
.map(Person::getName)
.collect(Collectors.toCollection(HashSet::new));
//工资总数
Long salaryCountCollect = personArrayList.stream()
.collect(Collectors.counting());
System.out.println("salaryCountCollect = " + salaryCountCollect);
//工资平均值
Double salaryAvgCollect = personArrayList.stream()
.collect(Collectors.averagingDouble(Person::getSalary));
System.out.println("salaryAvgCollect = " + salaryAvgCollect);
//工资总和
Double salarySumCollect = personArrayList.stream()
.collect(Collectors.summingDouble(Person::getSalary));
System.out.println("salarySumCollect = " + salarySumCollect);
//工资最大值
Optional<Person> salaryMaxCollect = personArrayList.stream()
.collect(Collectors.maxBy((person1, person2) -> Double.compare(person1.getSalary(), person2.getSalary())));
System.out.println("salaryMaxCollect = " + salaryMaxCollect);
//工资最小值
Optional<Double> salaryMinCollect = personArrayList.stream()
.map(Person::getSalary)
.collect(Collectors.minBy(Double::compare));
System.out.println("salaryMinCollect = " + salaryMinCollect);
//根据年龄分组
Map<Integer, List<Person>> ageGroupCollect = personArrayList.stream()
.collect(Collectors.groupingBy(Person::getAge));
System.out.println("ageGroupCollect = " + ageGroupCollect);
//多级分组
Map<Integer, Map<String, List<Person>>> ageMapGroupCollect = personArrayList.stream()
.collect(Collectors.groupingBy(Person::getAge, Collectors.groupingBy((e) -> {
if (e.getAge() <= 35) {
return "青年";
} else if (e.getAge() <= 50) {
return "中年";
} else {
return "老年";
}
})));
System.out.println("ageMapGroupCollect = " + ageMapGroupCollect);
//分区:满足条件的一个区,不满足条件的一个区
Map<Boolean, List<Person>> salaryPartitionCollect = personArrayList.stream()
.collect(Collectors.partitioningBy((e) -> e.getSalary() > 500));
System.out.println("salaryPartitionCollect = " + salaryPartitionCollect);
}
}
并行流与串行流
串行流:Stream上的操作是在一个线程中依次完成
并行流:Stream上的操作是在多个线程上同时执行
Stream并行流:就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。 Java8中将并行进行了优化,可以很容易的对数据进行并行操作。Stream API可以声明性地通过parallel()与sequential()在并行流与顺序流之间进行切换。
了解Fork/Join框架
Fork/Join框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join汇总。
Fork/Join框架与传统线程池的区别
采用工作窃取模式(work-stealing):
当执行新的任务时,它可以将其拆分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。 相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上。在一般线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。 而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行,那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行,这种方式减少了线程的等待时间,提高了性能。