什么是Stream?
也叫Stream流,是Jdk8开始新增的一套API (java.util.stream.*),可以用于操作集合或者数组的数据。
优势: Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好。
要使用Stream流,先检查自己电脑上配置的jdk版本是否在8以上,不是的话该更新了哦,Stream尊嘟好好玩。
jdk17下载链接在这里的呢,https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.msi
体验Stream流
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
要求是,把 list集合中所有以“张”开头,且是3个字的元素存储到一个新的集合当中。
-
解题分析:我们先来分析一下题意,1、以张开头的姓名 2、姓名是三个字
-
list集合调用stream()方法转为Stream流,再调用Stream流的相关方法
-
filter筛选出符合条件的对象,collect()方法收集生成的对象,Collectors.toList()把收集后的对象存储到List集合当中
-
List<String> names = new ArrayList<>();Collections.addAll(names, "张三丰", "张无忌", "周芷若", "赵敏", "张强");// 开始使用Stream流来解决这个需求。List<String> newNames = names.stream().filter(name -> name.startsWith("张") && name.length() == 3).collect(Collectors.toList());System.out.println("newNames = " + newNames);System.out.println("---------------------------------------");//不想存储到集合的话,也可以直接调用foreach方法,直接输出,效果等同names.stream().filter(name -> name.startsWith("张") && name.length() == 3).forEach(System.out::println);
除了用传统方法逐个进行添加之外,我们也可以直接使用 Collections工具类,调用addAll方法进行添加String对象
比如,介样子 List names = new ArrayList<>();
Collections.addAll(names, “张三丰”, “张无忌”, “周芷若”, “赵敏”, “张强”);
Stream流的常用方法
TreeMap<String, ArrayList<String>> citys = new TreeMap<>();ArrayList<String> su = new ArrayList<>();ArrayList<String> e = new ArrayList<>();ArrayList<String> ji = new ArrayList<>();Collections.addAll(su, "南京", "扬州", "苏州", "无锡", "常州");Collections.addAll(e, "武汉市", "孝感市", "十堰市", "宜昌市", "鄂州市");Collections.addAll(ji, "石家庄市", "唐山市", "邢台市", "保定市", "张家口市");citys.put("江苏省", su);citys.put("湖北省", e);citys.put("河北省", ji);ArrayList<String> strings = citys.get("湖北省");strings.forEach(System.out::println);//迭代器遍历查找,根据键找值,再逐层进行筛选Set<Map.Entry<String, ArrayList<String>>> entries = citys.entrySet();Iterator<Map.Entry<String, ArrayList<String>>> iterator = entries.iterator();while (iterator.hasNext()) {Map.Entry<String, ArrayList<String>> next = iterator.next();String key = next.getKey();//找到合适的键,进行匹配,符合要求之后输出键对应的值if (key.equals("湖北省")) {ArrayList<String> nextValue = next.getValue();nextValue.forEach(System.out::println);}}Set<String> strings1 = citys.keySet();ArrayList<String> strings2 = citys.get("江苏省");
//Steam流式思想,调用双层forEach方法,逐级调用里面的对象元素citys.forEach((key, city) -> {System.out.print(key + ":");city.forEach(System.out::println);});}
}
Stream流的使用步骤
- 获取Stream流,Stream流代表一条流水线,并能与数据源建立连接。
- 调用流水线的各种方法对数据进行处理、计算。
- 获取处理的结果,遍历、统计、收集到一个新集合中返回
1、Stream是什么?有什么作用? 结合了什么技术?
简化集合、数组操作的API。结合了Lambda表达式。
2、说说Stream流处理数据的步骤是什么?
先得到集合或者数组的Stream流。
然后调用Stream流的方法对数据进行处理。
获取处理的结果。
Stream流训练:
把集合中所有以“张”开头,且是3个字的元素存储到一个新的集合
//concat 拼接方法Stream<String> str1 = Stream.of("A", "B", "C");Stream<String> str2 = Stream.of("1", "2", "3");//拼接流str1和str2Stream.concat(str1,str2).forEach(System.out::println);
//拼接流str1和str2List<String> collect = Stream.concat(Stream.of(names), Stream.of(signal)).collect(Collectors.toList());collect.stream().forEach(System.out::println);
获取Stream流
-
Collection提供了专门的集合对象Stream流获取方法,default Stream stream()
-
获取 集合 的Stream流
-
List<String> list = new ArrayList<>(); Stream<String> stream = names.stream();//集合直接调用stream()方法,获取Stream流
-
-
获取 数组 的Stream流
-
数组获取Stream流的方式有两种,使用Arrays类和Stream类
-
Arrays类提供的Stream方法获取当前数组的Stream流
-
Stream类提供的方法of(T… values)获取当前接收数据的Stream流
-
int[] a = {1, 2, 3, 4, 5, 6}; String[] str = new String[]{"A", "B", "C"}; //public static <T> Stream<T> stream(T[] array) Arrays.stream(a).forEach(System.out::println);//先转为Stream流,才可以调用Stream流里面的相关方法 //public static<T> Stream<T> of(T... values) Stream.of(str).forEach(System.out::println);
-
Stream流常见的中间方法
-
中间方法指的是调用完成后会返回新的Stream流,可以继续使用(支持链式编程)。
-
Stream<T> filter(Predicate<? super T> predicate) //用于对流中的数据进行过滤。 Stream<T>sorted() //对元素进行升序排序 Stream<T> sorted(Comparator<? super T> comparator) //按照指定规则排序 Stream<T>limit(long maxSize) //获取前几个元素 Stream<T> skip(long n) //跳过前几个元素 Stream<T> distinct() //去除流中重复的元素。 <R> Stream<R> map(Function<? super T,? extends R> mapper) //对元素进行加工,并返回对应的新流 static <T> Stream<T> concat**(Stream a, Stream b) //合并a和b两个流为一个流
Stream常见的终结方法
-
终结方法指的是调用完成后,不会返回新Stream了,没法继续使用流了。
-
void forEach(Consumer action) //对此流运算后的元素执行遍历 long count() //统计此流运算后的元素个数 Optional<T> max(Comparator<? super T> comparator) //获取此流运算后的最大值元素 Optional<T> min(Comparator<? super T> comparator) //获取此流运算后的最小值元素
Stream流常见方法、中间方法、终结方法的综合实战
-
实战目标:掌握Stream流提供的常见、中间、终结方法。
-
前期数据准备
-
import java.util.Objects; public class Student {//学生类private String name;//姓名private int age;//年龄private double height;//身高private String sex;//性别private String address;//家庭地址@Overridepublic String toString() {return "学生姓名:" + name + ", 年龄:"+ age + ", 身高:" + height + ", 性别:" + sex + ", 家庭住址:" + address +'。';}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public Student() {}public Student(String name, int age, double height,String sex,String address) {this.name = name;this.age = age;this.height = height;this.sex = sex;this.address = address;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public double getHeight() {return height;}public void setHeight(double height) {this.height = height;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name);} }
-
Student s1 = new Student("林风", 26, 172.5,"男","苏州市"); Student s2 = new Student("赵琳", 26, 162.5,"女","兰州市"); Student s3 = new Student("音音", 23, 160.6,"女","西安市"); Student s4 = new Student("姜维", 25, 169.0,"男","天水市"); Student s5 = new Student("林锋", 35, 183.3,"女","深圳市"); Student s6 = new Student("李广", 34, 168.5,"男","天水市");
训练1:已知如下数据,找出成绩大于等于60分的数据,并升序后,再输出。
-
List<Double> scores = new ArrayList<>(); Collections.addAll(scores, 88.5, 100.0, 60.0, 99.0, 9.5, 99.6, 25.0);
-
解题过程:
-
// 因为分数是double类型,排序的时候直接调用double的封装类Double进行排序scores.stream().filter(score->(score>=60)).sorted((o1,o2)->Double.compare(o1,o2)).forEach(System.out::println);
-
训练2:已知students学生集合,找出年龄大于等于23,且年龄小于等于30岁的学生,并按照年龄降序输出.
-
解题过程:
students.stream().filter(student -> student.getAge()>=23&&student.getAge()<=30).sorted(((o1,o2)-> Integer.compare(o2.getAge(),o1.getAge()))).forEach(System.out::println);//首先转换为stream流,然后调用filter进行筛选,再降序最后打印输出列表内容,严格按照题意
训练3:已知students学生集合,取出身高最高的前3名学生,并输出。
-
解题过程
students.stream().sorted(((o1,o2)-> Double.compare(o2.getHeight(),o1.getHeight()))).limit(3).forEach(System.out::println);
训练4:取出身高倒数2名学生,并输出学生信息。
-
解题过程
students.stream().sorted(((o1,o2)-> Double.compare(o1.getHeight(),o2.getHeight()))).limit(2).forEach(System.out::printn);
训练5:找出身高超过168的学生叫什么名字,要求去除重复的名字,再输出。
-
解题过程
students.stream().filter(student -> student.getHeight()>=168).map(stu->stu.getName())// 使用Map方法将学生对象转换为名字数据.distinct()//名字字符串的去重.forEach(System.out::println); /**distinct去重复,自定义类型的对象(希望内容一样就认为重复,重写hashCode,equals)学生集合中的数据是学生对象,要求获取学生的名字,并且去重输出。如何在Stream中将Student数据转换为String数据? 可以使用map方法完成转换**/
-