引言
前面小猿总结了下java8中的新特新---Lambda表达式,不熟悉的小伙伴可以查看,这篇文章会用到lambda部分知识
这里小猿将介绍另一大java8引入的语法特性---Stream(流操作)
要知道什么是流式操作(Stream)操作,首先介绍一些什么是流操作,这里通过一个小小的案例看看流操作
//定义一个entity类Person public class Person { private String name; private int age; public String getName() { return name; } //这里修改返回类型为Person public Person setName(String name) { this.name = name; return this; } public int getAge() { return age; } //这里修改返回类型为Person public Person setAge(int age) { this.age = age; return this; } public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
关键代码
public class Demo { public static void main(String[] args) { Person person = new Person(); person.setName("李四").setAge(16); } }
通过上面代码我们可以分析当设置完姓名李四之后,我们还能接着设置年龄,这种用上一个过程的结果接着做另一件事的操作就是流操作。也就是说流只是一个计算的过程,并不会存储源对象,下面详细看看流式操作。
Stream实现步骤
1.获取数据源
// 方式一:java8对collection集合的接口扩展,支持创建流 List<String> list = new ArrayList<>(); Stream<String> stream = list.stream();// 返回一个顺序流 Stream<String> stream2 = list.parallelStream();// 返回一个并行流 // 方式二:通过Arrays静态方法Stream Person[] person = new Person[10]; Stream<Person> stream3 = Arrays.stream(person); // 方式三:通过stream的静态方法.of Stream<String> stream4 = Stream.of("aa", "bb"); // 方式四:无限流 // 使用iterate创建无限流 0, (x)->x+2中0表示种子,可以查看源码 Stream<Integer> stream5 = Stream.iterate(0, (x) -> x + 2); // 使用生成创建无限流,使用generate,比如生成随机数流 Stream.generate(()->Math.random());
2.对数据进行处理(过滤 映射)每一步得到一个流,成为中间操作
// 首创建一个集合流 List<Person> persons = Arrays.asList( new Person("李四", 12),new Person("张三", 15), new Person("网二", 18),new Person("王哈", 28),new Person("网二", 18)); Stream<Person> pStream = persons.stream();
筛选与切片
主要API
filter(Predicate p) 接收 Lambda , 从流中排除某些元素。
distinct() 筛选,通过流所生成元素的hashCode() 和 equals() 去 除重复元素 (需要重写对象得hashcode和equals方法)
limit(long maxSize) 截断流,使其元素不超过给定数量。
skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素 不足 n 个,则返回一个空流。与 limit(n) 互补
//演示filter(Predicate p)和distinct()API,查询年龄大于15,去重的人的信息 pStream.filter((x) -> x.getAge() > 15) .distinct() .forEach(System.out::println);
结果
Person [name=网二, age=18]
Person [name=王哈, age=28]
映射
主要的API
map(Function f) 接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。
mapToDouble(ToDoubleFunction f) 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的
DoubleStream。 mapToInt(ToIntFunction f) 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的
IntStream。 mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的
LongStream。 flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流
// 演示map(Function f) 将所有的person年龄+2 pStream.map((p)->p.getAge()+2).forEach(System.out::println);
排序
主要API
sorted() 产生一个新流,其中按自然顺序排序
sorted(Comparator comp) 产生一个新流,其中按比较器顺序排序
//创建一个流 List<String> list = Arrays.asList("aaa","bbb","ccc","dd"); //自然排序 list.stream().sorted().forEach(System.out::println);
// 首创建一个集合流 List<Person> persons = Arrays.asList( new Person("李四", 12), new Person("张三", 15), new Person("网二", 18), new Person("王哈", 28), new Person("张二", 18)); persons.stream().sorted((a, b) -> { if (a.getAge() == b.getAge()) { return a.getName().compareTo(b.getName()); } else { return a.getAge() - b.getAge(); } }).forEach(System.out::println);
3.对流中数据的整合(转成集合 数量),对流中的数据做了整合,称为最终操作
主要API
allMatch(Predicate p) 检查是否匹配所有元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicate p) 检查是否没有匹配所有元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意元素
// 首创建一个集合流 List<Person> persons = Arrays.asList( new Person("李四", 12), new Person("张三", 15), new Person("网二", 18), new Person("王哈", 28), new Person("张二", 18)); //演示取得第一个流 Optional<Person> pOptional = persons.stream().findFirst(); System.out.println(pOptional.get());//Person [name=李四, age=12]