StreamAPI概述
什么是StreamAPI?
从jdk1.8开始,java语言开始引入了一个全新的流式api ,把函数式编程风格应用到java语言中,使用streamAPI可以帮助我们更方便的操作集合,允许开发人员不改变原始数据情况下对集合进行操作,这使得代码更加简洁。
stream和Collection 区别
Collection:是静态的内存数据结构,强调的是数据
Stream API:是跟集合相关的计算操作,强调的是计算
总结:Collection面向的是内存,存储在内存中。StreamAPI面型的是CPU,通过CPU计算
StreamAPI操作步骤:
- 创建stream
- 中间操作
- 终止操作
Stream API的重要特点:
1. stream不会自己存储元素,只能对元素进行计算
2. Stream不会改变数据对象,反而可能会返回一个持有结果的新stream
3. Stream上的操作属于延迟操作,则就不能再调用其他中间操作或者终止操作
获取Stream兑现的第一种方式
public class StreamTest01 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Stream<Integer> stream = list.stream();//这是顺序流,单线程
System.out.println(stream);//java.util.stream.ReferencePipeline$Head@74a14482
Stream<Integer> parallelStream = list.parallelStream();//这是一个并行流 底层自动启动多线程 如果数据量非常庞大可以启用
}
}
获取Stream流的第三种方式
Stream<String> stream = Stream.of("dsa", "Dsa", "gds");
System.out.println(stream);
顺序流和并行流的理解
在前面获得的Stream对象的方式,我们都称之为“顺序流”,顺序流对Stream元素的处理是单线程的,即一个一个元素的处理,处理数据的效率较低。如果Stream流中的数据处理没有顺序要求,并且还希望可以并行处理Stream元素,那么就可以使用。
StreamAPI的中间操作
筛选
筛选,按照一定的规则校验流中的元素,将符合的元素提取到新的流的操作。
public class StreamTest04 {
public static void main(String[] args) {
StudentService.getStudents().stream().filter(new Predicate<Student>() {//filter属于中间操作 过滤 foreach和filter都是stream接口方法
//由于Stream支持链式
@Override
public boolean test(Student student) {
return student.getAge()>20;
}
}).forEach(new Consumer<Student>() {
@Override
public void accept(Student student) {
System.out.println(student);
}
});
//Lambda方式
System.out.println("---------------------");
StudentService.getStudents().stream().filter(student -> student.getAge()>20).forEach(System.out::println);
}
}
映射
public class StreamTest05 {
public static void main(String[] args) {
//将字符串的字母转换为大写字母 匿名内部类方式
Stream.of("abc","fdsDFD","gfd").map(new Function<String, String>() {
@Override
public String apply(String s) {
return s.toUpperCase();
}
}).forEach(System.out::println);
//Lambda表达式方式
Stream.of("fds","gsdf","fds").map(String::toUpperCase).forEach(System.out::println);
}
}
将多个集合中的数据合并到一格流中
//匿名
List<Integer>list = new ArrayList<>();
list.add(1);
list.add(1);
list.add(1);
list.add(1);
List<Integer>list1 = new ArrayList<>();
list1.add(2);
list1.add(2);
list1.add(2);
list1.add(2);
Stream<List<Integer>> twoListStream = Stream.of(list,list1);
twoListStream.flatMap(new Function<List<Integer>, Stream<?>>() {
@Override
public Stream<?> apply(List<Integer> integers) {
return integers.stream();
}
}).forEach(System.out::println);
//Lambda
Stream.of(list,list1).flatMap(List<Integer>::stream).forEach(System.out::println);
Stream中间操作之去重distinct
Stream.of(1,1,1,1,1,1,2,3,4,4,5,6).distinct().forEach(System.out::println);
去对象重是基于hacode+equals方法
Stream中间操作排序
Stream.of(1,2,3,4,3,2,4,3).sorted().forEach(System.out::println);
比较对象时需要实现Comparable方法
Stream中间操作之hebing
Stream<Integer> stream = Stream.of(1, 2, 3);
Stream<Integer> stream1 = Stream.of(4,5,6);
Stream.concat(stream1,stream).forEach(System.out::println);
Stream API的终止操作
触发终止操作才会真正执行中间操作,并且终止操作会导致Stream失效,也就不能再执行中间操作或者终止操作
遍历 Foreach
匹配Match
Stream.of(1,2,3,4).allMatch(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer.equals(3);
}
});
//简化
Stream.of(1,2,3,4).allMatch(value->value.equals(3));//全部匹配返回true
Stream终止操作 归约(reduce)
public class StreamTest09 {
public static void main(String[] args) {
//将集合中的所有元素求和
Stream.of(1,2,3,4).reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) {
return integer+integer2;
}
}).get();
//获取最大长度元素
System.out.println(Stream.of("dsa", "fsdafs", "d", "dd").reduce((s, s2) -> s.length() > s2.length() ? s : s2).get());
//获取学生最大年龄
System.out.println(StudentService.getStudents().stream().map(Student::getAge).max(Integer::compareTo).get());
}
}