也叫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
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);
});
}
}
1、Stream是什么?有什么作用? 结合了什么技术?
简化集合、数组操作的API。结合了Lambda表达式。
2、说说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);
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 Stream stream(T[] array)
Arrays.stream(a).forEach(System.out::println);//先转为Stream流,才可以调用Stream流里面的相关方法
//public static Stream of(T... values)
Stream.of(str).forEach(System.out::println);
中间方法指的是调用完成后会返回新的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了,没法继续使用流了。
void forEach(Consumer action) //对此流运算后的元素执行遍历
long count() //统计此流运算后的元素个数
Optional<T> max(Comparator<? super T> comparator) //获取此流运算后的最大值元素
Optional<T> min(Comparator<? super T> comparator) //获取此流运算后的最小值元素
实战目标:掌握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方法完成转换**/