什么是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和str2
Stream.concat(str1,str2)
.forEach(System.out::println);
//拼接流str1和str2
List<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;//家庭地址 @Override public 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; } @Override public 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); } @Override public 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方法完成转换**/
-