工作流:stream()
一.创建Stream() 的四种方式:
1)通过Collection的stream()方法(串行流)或ParallelStream()方法(并行流)创建Stream.
@Test
public void test1(){
List<String>list=new Arraylist<String>();
Stream<String>stream1=list.stream();
Stream<String>stream2=list.paralleltream();
}
2)通过Arrays的静态stream()方法获取数组流
@Test
public void test2 () {
IntStream stream = Arrays.stream(new int[]{3,5});
}
3)通过Stream类中的of()静态方法获取流
@Test
public void test3 () {
Stream<String>stream=Stream.of("1234","wuhan");
}
4)创建无限流(迭代、生成)
@Test
public void test4() {
//迭代(需要传入一个种子,也就是起始值,然后传入一个一元操作)
Stream<Integer>stream1=Stream.iterate(2,(x)->x*2);
//生成(无限产生对象)
Stream<Double>Stream2=Stream.generate(()->Math.random());
}
二.Stream中间操作
1)筛选切片
①filter–接收Lambda,从流中排出某些元素
@Test
public void test5 () {
//内部迭代:此过程中我们自己没有做过迭代操作,由stream API进行迭代
Stream<Person>stream=list.stream().filiter((e)->{
System.out.println("Stream() Api 中间操作");
return e.getAge()>30; //过滤输出,只输出age>30的那部分数据
});
//终止操作:只有执行终止操作才会执行全部。即延迟加载
stream.forEach(System.out : : println);
}
//下面我们来看一个外部的迭代方案:
@Test
public void test6 () {
//外部迭代
Iterator<Person> it = list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
②limit–截断流,使其元素不能超过给定的数量
//过滤之后取前2个值,
list.stream(). filiter( (e)->e.getAge>30).limit(2).forEach(System.out : : println);
2)跳过2个元素skip()
list.stream(). filiter( (e)->e.getAge>30).skip(2).forEach(System.out : : println);
3)筛选–使用distinct()去除重复的元素
list.stream().distinct().forEach(System.out : : println):
注意:distinct 需要实体中重写hashCode()和 equals()方法才可以使用
4)映射
① map,将元素转换成其他形式的数据或者提取信息,需要接收一个函数作为参数,该函数会被应用到每一个元素上,并将其映射成为一个新的元素
@Test
public void test () {
//将流中的每一个元素都映射到map的函数中,每个元素执行这个函数,再返回
List<String> list=Arrays.asList("aaa","bbb","ccc","ddd");
list.stream().map( (e)->e.toUpperCase()).forEach(System.out::println);
//获取Person中的每一个人的名字name,再返回一个集合
List<String>nameList=this.list.stream().map(Person : : getName).collect(Collectors.toList());
}
②flatMap -- 接收一个函数作为参数,将流中的每个值都换成一个流,然后把所有的流连接成一个流
public class StreamAPI_Test{
@Test
public void test2 () {
StreamAPI_Test s =new StreamAPI_Test();
List<String>list=Arrays.asList("aaa","bbb","ccc","ddd");
list.stream().flatMap( (e)->s.filterCharacter(e)).forEach(System.out : : println);
//如果使用map则需要这样写
list.stream().map( (e)->s.filterCharacter(e).forEach( (e)->{
e.forEach(System.out : : println)
});
}
//将一个字符串转换为流
public Stream<Character> filterCharacter(String str){
List<Character> list = new ArrayList<>();
for (Character ch : str.toCharArray()) {
list.add(ch);
}
return list.stream();
}
}
注意:其实map方法就相当于Collection的add()方法,如果add的是一个集合,就会变成二维的数组,
而flatMap则相当于Collection的addAll()方法,参数如果是集合的话,只是将2个集合合并,而不是变成二维的数组。
5)排序
sorted 有两种方法,一种是不传任何的参数,叫自然排序,还有一种需要传Comparator接口参数,叫做:定制排序
public void test () {
//自然排序
List<Person> persons=list.stream().sorted().collect(Collectors.toList());
//定制排序
List<Person>persons1=list.stream().sorted((e1,e2)->{
if(e1.getAge()==e2.getAge()){
return 0;
}esle if (e.getAge()>e2.getAge()){
return 1;
}else{
return -1;
}
}).collect(Collectors.toList());
}
三.Stream终止操作
1)查找与匹配
① allMatch–检查是否匹配所有的元素
//判断集合中每一个对象的状态属性是否都是:Free
public void test(){
boolean b = list.stream().allMatch( (e)->Free.equals(e.getStatus()));
System.out.println(b);
}
②anyMatch–检查集合中是否至少有一个匹配
public void test(){
boolean b = list.stream().anyMatch( (e)->Free.equals(e.getStatus()));
System.out.println(b);
}
③noneMatch()–检查是否没有一个匹配
public void test(){
boolean b = list.stream().noneMatch( (e)->Free.equals(e.getStatus()));
System.out.println(b);
}
④findFirst–返回第一个元素
public void test() {
Optional<Person> person = persons.stream().findFirst();
System.out.println(person);
//使用orElse()进行了逻辑处理,避免出现空指针异常
person.orElse(new Person("王五", "男", 35, Status.BUSY));
}
⑤findAny()–返回当前流中的任意一个元素
⑥count–返回流中元素的总个数
⑦max–返回流中的最大值
public void test() {
Optional<Person> person = persons.stream().max((e1,e2)->Double.compare(e1.getAge(),e2.getAge()));
}
⑧min --返回流中的最小值
2)归约(可以将流中元素反复结合在一起,得到一个值)
①. reduce(T identitty,BinaryOperator)首先,需要传一个起始值,然后,传入的是一个二元运算。
public void test() {
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = list.stream().reduce(0, (x, y) -> x + y);
}
②. reduce(BinaryOperator)此方法相对于上面方法来说,没有起始值,则有可能结果为空,所以返回的值会被封装到Optional中。
public void test() {
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Optional<Integer> sum = list.stream().reduce(Integer :: sum);
}
3)收集collect(将流转换为其他的形式,接收一个Collector接口的实现,用于给其他的Stream中元素做汇总的方法)
Collector接口中的实现决定了如何对流执行收集操作(如收集到List,Set,Map),但是Collectors实现类提供了很多的静态的方法,可以方便地创建常见的收集器实例。
①Collectors.toList() 将流转换成List
List<String>namesList=this.list.stream().map(Person :: getName).collect(Collectors.toList());
②Collectors.toSet() 将流转换成Set
List<String>namesList=this.list.stream().map(Person :: getName).collect(Collectors.toSet());
③Collectors.toCollection() 将流转换成其他类型的集合
LinkedList<String>namesList=this.list.stream().map(Person :: getName).collect(Collectors.toCollection(LinkedList :: new));
④. Collectors.counting() 计算集合中元素个数
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Long count = list.stream().collect(Collectors.counting());
⑤ Collectors.averagingInt() 、 Collectors.averagingDouble()、 Collectors.averagingLong() 平均数
三个方法都可以求平均数,不同之处在于传入得参数类型不同, 返回值都为Double
public void test() {
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Double avg = list.stream().collect(Collectors.averagingInt((x) -> x));
}
⑥.Collectors.summingInt() 、Collectors.summingDouble()、 Collectors.summingLong() 求和,
者三个方法都可以求总数,不同之处在于传入得参数类型不同,
返回值为Integer, Double, Long
public void test28() {
List<Integer> list = Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = list.stream().collect(Collectors.summingInt((x) -> x));
}
⑦. Collectors.maxBy() 求最大值
Optional<Integer>max=list.stream().collect(Collectors.maxBy( (x , y)->Integer.compare(x , y)));
⑧. Collectors.minBy() 求最小值
代码类似第七条
⑨. Collectors.groupingBy()分组 ,返回一个map
Map<String,Map<Status, List<Person>>>personMap=list.stream().collect(Collectors.groupBy(Person :: getSex))
//还可以实现多级分组
Map<String,Map<Status, List<Person>>>personMap=list.stream().collect(Collectors.groupBy(Person :: getSex,Collectors.groupBy(x)-+>x.getAge>30));
⑩. Collectors.partitioningBy() 分区,参数中传一个函数,返回true,和false 分成两个区
复制代码
1 /**
2 * Collectors.partitioningBy() 分区,参数中传一个函数,返回true,和false 分成两个区
3 */
4 @Test
5 public void test32() {
6 Map<Boolean, List> personMap = list.stream().collect(Collectors.partitioningBy((x) -> x.getAge() > 30));
7 }
复制代码
上面就是Stream的一些基本操作,只要勤加练习就可以灵活使用,而且效率大大提高。
stream工作流对List,Set,Map等进行排序:
1.按照自然顺序进行排列
list.stream().sorted();
2.使用Comparator中的reverseOrder()方法,实现反转排序
list.stream().sorted(Comparator.reverseOrder());
3.按照表格的某一个字段进行自然排序
list.stream().sorted(Comparator.comparing(Student::getAge));
4.按照表格的某一个字段进行反转排序
list.stream().sorted(Comparator.comparing(Student::getAge).reversed());
/**********************************/
代码demo:
@Data
@ToString
public class Student implements Comparable<Student> {
private int id;
private String name;
private int age;
}
List排序:
List<Student> list = new ArrayList<Student>();
list.add(new Student(1, "Mahesh", 12));
list.add(new Student(2, "Suresh", 15));
list.add(new Student(3, "Nilesh", 10));
//遍历list自然正序排列
List<Student>slist=list.stream().sorted().collect(Collectors.toList());
slist.forEach(e->System.out.println("Id:"+e.getId()+",Name"+e.getName()+",Age:"+e.getAge()))
Id:1, Name: Mahesh, Age:12
Id:3, Name: Nilesh, Age:10
Id:2, Name: Suresh, Age:15
//遍历list自然反序排列
slist=list.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
slist.forEach(e->System.out.println("Id:"+e.getId()+",Name"+e.getName()+",Age:"+e.getAge()))
Id:2, Name: Suresh, Age:15
Id:3, Name: Nilesh, Age:10
Id:1, Name: Mahesh, Age:12
//遍历list根据age字段正序排列:
slist=list.stream().sorted(Comparator.comparing(Student::getAge)).collect(Collectors.toList());
slist.forEach(e->System.out.println("Id:"+e.getId()+",Name"+e.getName()+",Age:"+e.getAge()))
Id:3, Name: Nilesh, Age:10
Id:1, Name: Mahesh, Age:12
Id:2, Name: Suresh, Age:15
//遍历list根据age字段反序排列:
slist=list.stream().sorted(Comparator.comparing(Student::getAge).reversed()).collect(Collectors.toList());
slist.forEach(e->System.out.println("Id:"+e.getId()+",Name"+e.getName()+",Age:"+e.getAge()))
Id:2, Name: Suresh, Age:15
Id:1, Name: Mahesh, Age:12
Id:3, Name: Nilesh, Age:10
Set 排序:
Set<Student> set = new HashSet<Student>();
set.add(new Student(1, "Mahesh", 12));
set.add(new Student(2, "Suresh", 15));
set.add(new Student(3, "Nilesh", 10));
//自然正序排列:
set.stream().sorted().forEach(e->System.out.println("Id:"+e.getId()+",Name"+e.getName()+",Age:"+e.getAge()))
Id:1, Name: Mahesh, Age:12
Id:3, Name: Nilesh, Age:10
Id:2, Name: Suresh, Age:15
//自然反序排列:
set.stream().sorted(Comparator.reverseOrder()).forEach(e->System.out.println("Id:"+e.getId()+",Name"+e.getName()+",Age:"+e.getAge()))
Id:2, Name: Suresh, Age:15
Id:3, Name: Nilesh, Age:10
Id:1, Name: Mahesh, Age:12
//遍历set根据age字段正序排列:
set.stream().sorted(Comparator.comparing(student::getAge)).forEach(e->System.out.println("Id:"+e.getId()+",Name"+e.getName()+",Age:"+e.getAge()))
Id:3, Name: Nilesh, Age:10
Id:1, Name: Mahesh, Age:12
Id:2, Name: Suresh, Age:15
//遍历set根据age字段反序排列:
set.stream().sorted(Comparator.comparing(Student::getAge).reversed()).forEach(e->System.out.println("Id:"+e.getId()+",Name"+e.getName()+",Age:"+e.getAge()))
Id:2, Name: Suresh, Age:15
Id:1, Name: Mahesh, Age:12
Id:3, Name: Nilesh, Age:10
//Map排序:
Map<Integer, String> map = new HashMap<>();
map.put(15, "Mahesh");
map.put(10, "Suresh");
map.put(30, "Nilesh");
//根据value正序排序
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).forEach(e->System.out.println("Key:"+e.getKey()+",Value:"+e.getValue()))
//输出结果:
Key: 15, Value: Mahesh
Key: 30, Value: Nilesh
Key: 10, Value: Suresh
//根据key正序排序
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEach(e->System.out.println("Key:"+e.getKey()+",Value:"+e.getValue()))
//输出结果:
Key: 10, Value: Suresh
Key: 15, Value: Mahesh
Key: 30, Value: Nilesh
//当Map中的Value 是一个自定义对象时:
Map<Integer, Student> map = new HashMap<>();
map.put(1, new Student(1, "Mahesh", 12));
map.put(2, new Student(2, "Suresh", 15));
map.put(3, new Student(3, "Nilesh", 10));
//map的Entry()中的value-->student的name属性自然正序排列
map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).forEach(e->{
Integer key =(Integer)e.getKey();
Student stu=(Student)e.getValue();
System.out.println("Key:"+key+",value:("+stu.getId()+","+)System.out.println("Key:"+key+",value:("+stu.getId()+","++ std.getName()+", "+ std.getAge()+")");
});
//排序的结果:
Key: 1, value: (1, Mahesh, 12)
Key: 3, value: (3, Nilesh, 10)
Key: 2, value: (2, Suresh, 15)