Stream (流) :数据通道,用于操作数据源(数组、集合等)所生成的元素序列。
1、 Stream 自己不会存储数据
2、Stream不会改变源对象,返回的是一个持有操作结果的新的Stream.
3、Stream是延迟执行的(等到需要结果的时候才会执行)。
Stream的三个步骤:
1、创建Stream
//1.可以通过Collection系列集合提供的stream()获取串行流 或paralleStream()获取并行流 List<String> list = new ArrayList<>(); Stream<String> stream = list.stream(); //2.通过Arrays中的静态方法获取 stream() 获取数组流 Book[] books = new Book[10]; Stream<Book> stream1 = Arrays.stream(books); //3.通过Stream类中的静态方法 of() 创建流 Stream<Book> stream2 = Stream.of(books); //4.创建无限流(无穷尽) //迭代 Stream<Integer> stream3 = Stream.iterate(0,x->x+2); // stream3.forEach(System.out::println); stream3.limit(10).forEach(System.out::println);//只取前10个 //生成 Stream.generate(()->Math.random()).limit(5).forEach(System.out::println);
2、中间操作
package com.example.pojo; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; import java.util.Date; import java.util.Objects; public class Book implements Serializable{ private static final long serialVersionUID = -5682718161792139284L; private Integer id; private String name; private String author; @JsonIgnore private Float price; @JsonFormat(pattern = "yyyy-MM-dd") private Date publicationDate; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } public Date getPublicationDate() { return publicationDate; } public void setPublicationDate(Date publicationDate) { this.publicationDate = publicationDate; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Book book = (Book) o; return Objects.equals(id, book.id) && Objects.equals(name, book.name) && Objects.equals(author, book.author) && Objects.equals(price, book.price) && Objects.equals(publicationDate, book.publicationDate); } @Override public int hashCode() { return Objects.hash(id, name, author, price, publicationDate); } }
//筛选与切片 //filter:接收Lambda, 从流中排除某些元素 //limit(n):截断流,使其元素不超过给定数量,返回前n个元素组成的流 //skip(n):跳过元素,返回去掉了前n个的流,元素个数不足n个返回空流。与limit(n)互补 //distinct:筛选, 通过流所生成元素的hashCode()和equals()方法去除重复元素。 Book[] books = new Book[10]; //中间操作:多个中间操作可连接起来形成一个流水线,但中间操作不会立即执行任何处理,除非流水线上触发终止操作时才会一次性全部处理,称为“随性求值” // 内部迭代,迭代操作由Stream API 完成 List<Book> bookList = (List<Book>) Arrays.asList(books).stream() .filter(e -> e.getPrice()>10f).limit(2); //终止操作:一次性执行全部操作, 即: 随性求值 bookList.forEach(System.out::println); List<Book> bookList2 = (List<Book>) Arrays.asList(books).stream() .filter(e -> { System.out.println("Stream API 的中间操作"); return e.getPrice()>10f; }).limit(2);//limit 一但发现了指定数据的数据就返回不继续筛选。 bookList2.forEach(System.out::println); List<Book> bookList3 = (List<Book>) Arrays.asList(books).stream() .filter(e -> { System.out.println("Stream API 的中间操作"); return e.getPrice()>10f; }).skip(2); bookList3.forEach(System.out::println); //去重,Book必须重写hashCode()和equals()方法 List<Book> bookList4 = (List<Book>) Arrays.asList(books).stream() .distinct(); bookList4.forEach(System.out::println);
public static Stream<Character> filterCharacter(String str){ List<Character> list = new ArrayList<>(); for(Character c : str.toCharArray()){ list.add(c); } return list.stream(); }
//映射 //map: 接收Lambda, 将元素转换成其它形式可提取信息。接收一个函数作为参数,该函数会被应用到每个元素上并将其映射成一个新元素 //flatMap: 接收一个函数作为参数,将流中每一个值都换成另一个流,然后把所有流连接成一个流 List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee"); list.stream() .map(str -> str.toUpperCase()) //都转换成大写 .forEach(System.out::println); Book[] books = new Book[10]; Arrays.stream(books) .map(e->e.getName())//取出所有书名组成一个新的数组 .forEach(System.out::println); Arrays.stream(books) .map(Book::getName)//取出所有书名组成一个新的数组 .forEach(System.out::println); Stream<Stream<Character>> stream = list.stream().map(StreamTest::filterCharacter); stream.forEach(e -> e.forEach(System.out::println)); Stream<Character> stream1 = list.stream().flatMap(StreamTest::filterCharacter); stream1.forEach(System.out::println);
//排序 //sorted: 自然排序 (Comarable) //sorted(Comparator com): 定制排序 List<String> list = Arrays.asList("aaa","fff","bbb","ccc","ddd","eee"); list.stream().sorted().forEach(System.out::println); Book[] books = new Book[10]; List<Book> bookList = (List<Book>) Arrays.asList(books).stream() .sorted((e1,e2) -> { if(e1.getPrice().equals(e2.getPrice())){ return e1.getName().compareTo(e2.getName()); }else{ return e1.getPrice().compareTo(e2.getPrice());//升序 // return -e1.getPrice().compareTo(e2.getPrice());//降序 } }); bookList.forEach(System.out::println);
3、终止操作
package com.example.enums; import java.util.Objects; import java.util.stream.Stream; public enum Status { HAVING(1,"有货"), NON(2,"无货"), ; private final Integer type; private final String name; Status(Integer type, String name) { this.type = type; this.name = name; } public static Status of(Integer type){ Objects.requireNonNull(type,"是否有货"); return Stream.of(values()).filter(bean->bean.type.equals(type)) .findAny() .orElseThrow(() -> new IllegalArgumentException("是否有货为:"+ type + "的是否有货类型在枚举中不存在")); } }
package com.example.pojo; import com.example.enums.Status; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import java.io.Serializable; import java.util.Date; import java.util.Objects; public class Book implements Serializable{ private static final long serialVersionUID = -5682718161792139284L; private Integer id; private String name; private String author; @JsonIgnore private Float price; @JsonFormat(pattern = "yyyy-MM-dd") private Date publicationDate; private Status status; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } public Date getPublicationDate() { return publicationDate; } public void setPublicationDate(Date publicationDate) { this.publicationDate = publicationDate; } public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Book book = (Book) o; return Objects.equals(id, book.id) && Objects.equals(name, book.name) && Objects.equals(author, book.author) && Objects.equals(price, book.price) && Objects.equals(publicationDate, book.publicationDate) && status == book.status; } @Override public int hashCode() { return Objects.hash(id, name, author, price, publicationDate, status); } }
//查找与匹配 //allMatch:检查是否匹配所有元素 //anyMatch:检查是否匹配至少一个元素 //noneMatch:检查是否没有匹配所有元素 //findFirst:返回第一个元素 //findAny:返回当前流中的任意元素 //count:返回当前流中的总个数 //max:返回流中的最大值 //min:返回流中的最小值 Book[] books = new Book[10]; List<Book> bookList = (List<Book>) Arrays.asList(books); Boolean b = bookList.stream().allMatch(e->e.getStatus().equals(Status.HAVING)); Boolean b1 = bookList.stream().anyMatch(e->e.getStatus().equals(Status.HAVING)); Boolean b2 = bookList.stream().noneMatch(e->e.getStatus().equals(Status.NON)); Optional<Book> op = bookList.stream() .sorted((e1,e2) -> -e1.getPrice().compareTo(e2.getPrice())) .findFirst(); System.out.println(op.get()); Optional<Book> op2 = bookList.stream() //串行:一个一个找 .filter(e -> e.getStatus().equals(Status.HAVING)) .findAny(); System.out.println(op2.get()); Optional<Book> op3 = bookList.parallelStream() //并行:多头同时找 .filter(e -> e.getStatus().equals(Status.HAVING)) .findAny(); System.out.println(op3.get()); Long count = bookList.stream().count(); Optional<Book> op4 = bookList.stream() .max((e1,e2) -> e1.getPrice().compareTo(e2.getPrice())); System.out.println(op4.get()); Optional<Float> op5= bookList.stream() .map(Book::getPrice) .min(Float::compare); System.out.println(op5.get());
// 归约 : 将流中元素反复结合起来得到一个值 //reduce(T identity,BinaryOperator) //reduce(BinaryOperator) List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); Integer sum = list.stream().reduce(0,(x,y)->x+y); System.out.println(sum); Book[] books = new Book[10]; List<Book> bookList = (List<Book>) Arrays.asList(books); Optional<Float> sum2 = bookList.stream() .map(Book::getPrice) .reduce(Float::sum); System.out.println(sum2.get());
//收集 //collect: 将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中的元素做汇总的方法 Book[] books = new Book[10]; List<Book> bookList = (List<Book>) Arrays.asList(books); List<String> booknames = bookList.stream() .map(Book::getName) .distinct() .collect(Collectors.toList()); booknames.forEach(System.out::println); Set<String> booknames2 = bookList.stream() .map(Book::getName) .collect(Collectors.toSet()); booknames2.forEach(System.out::println); HashSet<String> booknames3 = bookList.stream() .map(Book::getName) .collect(Collectors.toCollection(HashSet::new)); booknames3.forEach(System.out::println); //总数 Long count = bookList.stream() .collect(Collectors.counting()); //平均数 Double avg = bookList.stream().collect(Collectors.averagingDouble(Book::getPrice)); //总和 Double sum = bookList.stream().collect(Collectors.summingDouble(Book::getPrice)); //最大值 Optional<Book> max = bookList.stream() .collect(Collectors.maxBy((e1,e2)->Float.compare(e1.getPrice(),e2.getPrice()))); //最小值 Optional<Book> min = bookList.stream() .collect(Collectors.minBy((e1,e2)->Float.compare(e1.getPrice(),e2.getPrice()))); //分组 Map<Status,List<Book>> map = bookList.stream() .collect(Collectors.groupingBy(Book::getStatus)); //多级分组 Map<Status,Map<String,List<Book>>> map2 = bookList.stream() .collect(Collectors.groupingBy(Book::getStatus,Collectors.groupingBy(e -> { if(e.getPrice()<10f){ return "秒杀"; }else if(e.getPrice()<20f){ return "促销"; }else{ return "现货"; } }))); //分区 Map<Boolean,List<Book>> map3 = bookList.stream() .collect(Collectors.partitioningBy(e->e.getPrice()<20f)); DoubleSummaryStatistics summaryStatistics = bookList.stream().collect(Collectors.summarizingDouble(Book::getPrice)); System.out.println(summaryStatistics.getMax()); System.out.println(summaryStatistics.getAverage()); System.out.println(summaryStatistics.getCount()); System.out.println(summaryStatistics.getSum()); System.out.println(summaryStatistics.getMin()); String str = bookList.stream() .map(Book::getName) .collect(Collectors.joining(",")); System.out.println(str);