1.体验Stream流
案例需求
按照下面的要求完成集合的创建和遍历
创建一个集合,存储多个字符串元素
把集合中所有以"张"开头的元素存储到一个新的集合
把"张"开头的集合中的长度为3的元素存储到一个新的集合
遍历上一步得到的集合
原始方式示例代码
package Stream;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class demo1 {public static void main(String[] args) {/*
案例需求
按照下面的要求完成集合的创建和遍历
- 创建一个集合,存储多个字符串元素
- 把集合中所有以"张"开头的元素存储到一个新的集合
- 把"张"开头的集合中的长度为3的元素存储到一个新的集合
- 遍历上一步得到的集合
*///集合的批量添加ArrayList<String> list1 = new ArrayList<>();Collections.addAll(list1, "张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤");ArrayList<String> list2 = new ArrayList<>();//- 把集合中所有以"张"开头的元素存储到一个新的集合//遍历list1把以张开头的元素添加到list2中。for (String name : list1) {if (name.startsWith("张")) {list2.add(name);}}System.out.println(list2);//- 把"张"开头的集合中的长度为3的元素存储到一个新的集合ArrayList<String> list3 = new ArrayList<>();for (String name : list2) {if(name.length()==3){list3.add(name);}}System.out.println(list3);}
}
使用Stream流示例代码
public class demo2 {public static void main(String[] args) {//使用Stream流示例代码//集合的批量添加ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));list1.stream().filter(name->name.startsWith("张")).filter(name->name.length()==3).forEach(name-> System.out.println(name));}
}
2.Stream流的常见生成方式
Stream流的思想
Stream流的三类方法
获取Stream流
创建一条流水线,并把数据放到流水线上准备进行操作
中间方法
流水线上的操作
一次操作完毕之后,还可以继续进行其他操作
终结方法
一个Stream流只能有一个终结方法
是流水线上的最后一个操作
生成Stream流的方式
Collection体系集合
使用默认方法stream()生成流, default Stream<E> stream()
Map体系集合
把Map转成Set集合,间接的生成流
数组
通过Arrays中的静态方法stream生成流
同种数据类型的多个数据
通过Stream接口的静态方法of(T... values)生成流
package Stream;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.stream.Stream;public class demo3 {public static void main(String[] args) {/*单列集合 default Stream<E> stream() Collection中的默认方法双列集合 无 无法直接使用stream流数组 public static <T> Stream<T> stream(T[] array) Arrays工具类中的静态方法一堆零散数据 public static<T> Stream<T> of(T... values) Stream接口中的静态方法
*///使用单列集合创建stream流ArrayList<String> list = new ArrayList<>();Collections.addAll(list,"aaa","bbb","ccc");list.stream().forEach(s->System.out.println(s));System.out.println("----------------------");//使用双列集合创建stream流HashMap<String,Integer> hm = new HashMap<>();hm.put("aaa",1);hm.put("bbb",2);hm.put("ccc",3);//第一种获取stream流//先获取一个键值对对象,把键值对对象放到了stream流,这里的s相当于每一个键值对对象hm.entrySet().stream().forEach(s-> System.out.println(s));//第二种获取stream流//先获取所有的键,把键放在stream流,这里的s相当于每一个键hm.keySet().stream().forEach(s-> System.out.println(s));System.out.println("----------------------");//使用数组创建stream流int []arr1 = {1,2,3,4,5};Arrays.stream(arr1).forEach(s-> System.out.print(s+" "));System.out.println();String[] arr2 = {"aaa","bbb","ccc"};Arrays.stream(arr2).forEach(s-> System.out.print(s+" "));System.out.println();//注意://Stream接口中静态方法of的细节//方法的形参是一个可变参数,可以传递一堆零散的数据,也可以传递数组//但是数组必须是引用数据类型的,如果传递基本数据类型,是会把整个数组当做一个元素,放到Stream当中。Stream.of(arr1).forEach(s-> System.out.println(s+" "));//[I@30dae81Stream.of(arr2).forEach(s-> System.out.println(s+" "));System.out.println("----------------------");//使用一堆零散数据创建stream流Stream.of(1,2,3,4,5).forEach(s-> System.out.print(s+" "));Stream.of("a","b","c","d","e").forEach(s-> System.out.print(s+" "));}
}
3.Stream流中间操作方法
-
概念
中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作
package Stream;import java.util.ArrayList;
import java.util.Collections;
import java.util.SortedMap;/*filter 过滤limit 获取前几个元素skip 跳过前几个元素注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据*/
public class demo4 {public static void main(String[] args) {//1. filter 过滤ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤");//filter 过滤 把张开头的留下,其余数据过滤不要list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));//注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据//list的集合还是不会变化System.out.println(list);System.out.println("====================================");//2 . limit 获取前几个元素list.stream().limit(3).forEach(s -> System.out.println(s));//张无忌", "周芷若", "赵敏System.out.println("====================================");//3. skip 跳过前几个元素list.stream().skip(3).limit(3).forEach(s -> System.out.println(s));//张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤}
}
package Stream;import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.Stream;/*distinct 元素去重,依赖(hashCode和equals方法)concat 合并a和b两个流为一个流注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据*/
public class demo5 {public static void main(String[] args) {ArrayList<String> list1 = new ArrayList<>();Collections.addAll(list1, "张无忌","张无忌","张无忌", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤");//1. distinct 元素去重,依赖(hashCode和equals方法)list1.stream().distinct().forEach(s->System.out.println(s));System.out.println("-------------------------------------");//2. concat 合并a和b两个流为一个流//创建一个新的集合ArrayList<String> list2 = new ArrayList<>();Collections.addAll(list2,"周芷若", "赵敏");Stream.concat(list1.stream(), list2.stream()).distinct().forEach(s->System.out.println(s));}
}
package Stream;import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Function;public class demp6 {public static void main(String[] args) {/*map 转换流中的数据类型注意1:中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程注意2:修改Stream流中的数据,不会影响原来集合或者数组中的数据*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌-15", "周芷若-14", "赵敏-13", "张强-20", "张三丰-100", "张翠山-40", "张良-35", "王二麻子-37", "谢广坤-41");//需求:只获取里面的年龄并进行打印//String->int//第一个类型:流中原本的数据类型//第二个类型:要转成之后的类型//apply的形参s:依次表示流里面的每一个数据//返回值:表示转换之后的数据//当map方法执行完毕之后,流上的数据就变成了整数//所以在下面forEach当中,s依次表示流里面的每一个数据,这个数据现在就是整数了/* list.stream().map(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {String[] arr = s.split("-");//张无忌-15String ageString = arr[1];//15int age = Integer.parseInt(ageString);return age;}}).forEach(s-> System.out.println(s));*/list.stream().map(s->Integer.parseInt(s.split("-")[1])).forEach(s-> System.out.println(s));}
}
4.Stream流终结操作方法
-
概念
终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作
-
常见方法
package Stream;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.function.IntFunction;public class demo7 {public static void main(String[] args) {/*void forEach(Consumer action) 遍历long count() 统计toArray() 收集流中的数据,放到数组中*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤");//void forEach(Consumer action) 遍历//Consumer的泛型:表示流中数据的类型//accept方法的形参s:依次表示流里面的每一个数据//方法体:对每一个数据的处理操作(打印)list.stream().forEach(s -> System.out.println(s));System.out.println("------------------------");//2. long count() 统计System.out.println(list.stream().count());System.out.println("-----------------------");//3. toArray() 收集流中的数据,放到数组中//Object[] arr1 = list.stream().toArray();//System.out.println(Arrays.toString(arr1));//IntFunction的泛型:具体类型的数组//apply的形参:流中数据的个数,要跟数组的长度保持一致//apply的返回值:具体类型的数组//方法体:就是创建数组//toArray方法的参数的作用:负责创建一个指定类型的数组//toArray方法的底层,会依次得到流里面的每一个数据,并把数据放到数组当中//toArray方法的返回值:是一个装着流里面所有数据的数组/* String[] arr = list.stream().toArray(new IntFunction<String[]>() {@Overridepublic String[] apply(int value) {return new String[value];}});System.out.println(Arrays.toString(arr));*/System.out.println(Arrays.toString( list.stream().toArray(value -> new String[value])));}
}
package Stream;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;public class demo8 {public static void main(String[] args) {/* collect(Collector collector) 收集流中的数据,放到集合中 (List Set Map)注意点:如果我们要收集到Map集合当中,键不能重复,否则会报错*/ArrayList<String> list = new ArrayList<>();Collections.addAll(list, "张无忌-男-15", "周芷若-女-14", "赵敏-女-13", "张强-男-20","张三丰-男-100", "张翠山-男-40", "张良-男-35", "王二麻子-男-37", "谢广坤-男-41");//收集List集合当中//需求://我要把所有的男性收集起来list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toList()).forEach(s -> System.out.println(s));System.out.println("----------------------");//收集Set集合当中//需求://我要把所有的男性收集起来//set集合与list区别就在于set能去重list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toSet()).forEach(s -> System.out.println(s));System.out.println("--------------------------------");//收集Map集合当中//谁作为键,谁作为值.//我要把所有的男性收集起来//键:姓名。 值:年龄/*toMap:参数一:表示键的生成规则参数二:表示值的生成规则参数一:Function泛型一:表示流中的每一个数据的类型泛型二:表示Map集合中键的数据类型方法apply形参:依次表示流里的每一个数据方法体: 生成键的代码返回值:已经生成的键参数二:Function泛型一:表示流中的每一个数据的类型泛型二:表示Map集合中值的数据类型方法apply形参:依次表示流里的每一个数据方法体: 生成值的代码返回值:已经生成的值*/Map<String, Integer> newmap = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(new Function<String, String>() {@Overridepublic String apply(String s) {//张无忌-男-15return s.split("-")[0];}}, new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.parseInt(s.split("-")[2]);}}));System.out.println(newmap);System.out.println("---------------------");Map<String, Integer> map = list.stream().filter(s -> "男".equals(s.split("-")[1])).collect(Collectors.toMap(s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[2])));System.out.println(map);}
}
5.练习
public class demo1 {public static void main(String[] args) {ArrayList<Integer> list = new ArrayList<>();Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9,10);list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList()).forEach(s->System.out.println(s));}
}
package lx;import java.util.ArrayList;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;public class demo2 {public static void main(String[] args) {ArrayList<Student> list = new ArrayList<>();Student s1 = new Student("zhangsan", 23);Student s2 = new Student("lisi", 24);Student s3 = new Student("wangwu", 25);list.add(s1);list.add(s2);list.add(s3);Map<String, Integer> newmap =list.stream().filter(student -> student.getAge() >=24).collect(Collectors.toMap(new Function<Student, String>() {@Overridepublic String apply(Student student) {return student.getName();}}, new Function<Student, Integer>() {@Overridepublic Integer apply(Student student) {return student.getAge();}}));System.out.println(newmap);System.out.println("-----------------");//lambda表达式Map<String, Integer> newmap2 = list.stream().filter(student -> student.getAge() > 24).collect(Collectors.toMap(student -> student.getName(), student -> student.getAge()));System.out.println(newmap2);}
package lx;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;public class demo3 {public static void main(String[] args) {/*现在有两个ArrayList集合,分别存储6名男演员的名字和年龄以及6名女演员的名字和年龄。姓名和年龄中间用逗号隔开。比如:张三,23要求完成如下的操作:1,男演员只要名字为3个字的前两人2,女演员只要姓杨的,并且不要第一个3,把过滤后的男演员姓名和女演员姓名合并到一起4,将上一步的演员信息封装成Actor对象。5,将所有的演员对象都保存到List集合中。备注:演员类Actor,属性有:name,age男演员: "蔡坤坤,24" , "叶齁咸,23", "刘不甜,22", "吴签,24", "谷嘉,30", "肖梁梁,27"女演员: "赵小颖,35" , "杨颖,36", "高元元,43", "张天天,31", "刘诗,35", "杨小幂,33"*///1.创建两个ArrayList集合ArrayList<String> manList = new ArrayList<>();ArrayList<String> womenList = new ArrayList<>();//2.添加数据Collections.addAll(manList, "蔡坤坤,24", "叶齁咸,23", "刘不甜,22", "吴签,24", "谷嘉,30", "肖梁梁,27");Collections.addAll(womenList, "赵小颖,35", "杨颖,36", "高元元,43", "张天天,31", "刘诗,35", "杨小幂,33");//3.男演员只要名字为3个字的前两人Stream<String> stream1 = manList.stream().filter(s -> s.split(",")[0].length() == 3).limit(2);//4.女演员只要姓杨的,并且不要第一个Stream<String> stream2 = womenList.stream().filter(s -> s.split(",")[0].startsWith("杨")).skip(1);//5,把过滤后的男演员姓名和女演员姓名合并到一起//Stream.concat(stream1,stream2);//6.将上一步的演员信息封装成Actor对象。//String -> Actor对象 (类型转换)//第一个类型:流中原本的数据类型//第二个类型:要转成之后的类型//apply的形参s:依次表示流里面的每一个数据//返回值:表示转换之后的数据//当map方法执行完毕之后,流上的数据就变成了Actor//所以在下面forEach当中,s依次表示流里面的每一个数据,这个数据现在就是Actor类型的数据了/* Stream.concat(stream1, stream2).map(new Function<String, Actor>() {@Overridepublic Actor apply(String s) {//赵小颖,35String[] arr = s.split(",");String name = arr[0];//赵小颖int age = Integer.parseInt(arr[1]);return new Actor(name, age);}});*///7,将所有的演员对象都保存到List集合中。List<Actor> newlist = Stream.concat(stream1, stream2).map(s -> new Actor(s.split(",")[0],Integer.parseInt(s.split(",")[1]))).collect(Collectors.toList());System.out.println(newlist);}
}