Stream流
创建不可变集合
不可以被修改的集合
在listm,set,map接口中都存在静态的of方法可以获取一个不可变集合
不能添加,不能删除,不能修改
/* 创建不可变的List集合 这是Jdk9的新特性 */ // List<String> list = List.of("张三","李四","王五","赵六"); /* 可以使用增强for循环 和 迭代器 遍历 */
Stream流
初识
/* 创建集合添加元素 完成下面需求 1.把所有以“张”开头的元素存到新集合 2.把“张”开头的,长度为3的再存储到一个新集合 3.遍历打印 */ ArrayList<String> list = new ArrayList<>(); list.add("张无忌"); list.add("周芷若"); list.add("赵敏"); list.add("张强"); list.add("张三丰"); //使用Stream流 list.stream().filter(name->name.startsWith("张")).filter(name->name.length()==3).forEach(name-> System.out.println(name)); /* //常规写法 //1.把所有以“张”开头的元素存到新集合 ArrayList<String> list01 = new ArrayList<>(); ArrayList<String> list02 = new ArrayList<>(); for (String name : list) { if (name.startsWith("张")){ list01.add(name); if (name.length()==3){ list02.add(name); } } } System.out.println(list01); System.out.println(list02); */
作用:结合Lambda表达式,简化集合,数组的操作
使用步骤:
-
先得到一条Stream流 并把数据放上去
-
利用Stream流中的API进行各种操作
-
中间方法 对流水线数据操作
-
终结方法 Steam流中最后一步
-
如何获取Stream流
-
单列集合 Collection中的默认方法
-
/* Stream流 */ //单列集合获取Stream流 ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"a","b","c","d","e"); // //获取到一条流水线 并把数据放到流水线上 // Stream<String> stream = list.stream(); // stream.forEach(new Consumer<String>() { // @Override // public void accept(String s) { // //s 依次表示流水线上的每一个数据 // System.out.println(s); // } // }); list.stream().forEach(s-> System.out.println(s));//等同与上面
-
-
双列集合 无法直接使用
-
/* Stream流 双列集合 无法直接使用Stream流 */ // HashMap<String, Integer> hashMap = new HashMap<>(); hashMap.put("aaa",111); hashMap.put("bbb",222); hashMap.put("ccc",333); hashMap.put("ddd",444); //获取Stream流 hashMap.keySet().stream().forEach(s-> System.out.println(s)); //结果 :aaa bbb ccc ddd //第二种获取Stream流 hashMap.entrySet().stream().forEach(s-> System.out.println(s)); //结果:aaa=111 ccc=333 bbb=222 ddd=444
-
-
数组 Arrays工具类中的静态方法
-
/* Stream流 数组获取 */ int[] arr={1,2,3,4,5,6}; String[] arr2 = {"a","b","c"}; //获取Stream流 Arrays.stream(arr).forEach(s-> System.out.println(s)); Arrays.stream(arr2).forEach(s -> System.out.println(s));
-
-
一堆零散数据 Stream接口中的静态方法
-
/* Stream流 一堆零散的数据 细节:Of方法的形参是一个可变参数,可以传递数组 数组必须是引用类型,如果传递基本类型,会把整个数组 当成一个元素,放到Stream流中 */ Stream.of(1,2,3,4,5).forEach(s-> System.out.println(s)); Stream.of("a","b","c","d","e").forEach(s-> System.out.println(s));
-
Stream流的中间方法
中间方法,返回新的的Stream流,原来的Stream流只能使用一次,建议使用链式编程
修改Stream流中的数据,不会影响原来的集合或者数组中的数据
filter过滤 limit获取前几个元素 skip获取后几个元素
/* stream流 */ ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤"); //filter 过滤 把张开头留下 /* list.stream().filter(new Predicate<String>() { @Override public boolean test(String s) { //匿名内部类写法 //如果返回值为True 表示当前数据留下 false 表示数据舍弃 return s.startsWith("张"); } }).forEach(s-> System.out.println(s)); list.stream() .filter(s -> s.startsWith("张")) .forEach(s -> System.out.println(s));//lambda表达式和上面一样功能 */ //limit 获取前几个元素 //skip 跳过前几个元素 list.stream().limit(3).forEach(s -> System.out.println(s));//3 就是三个元素 list.stream().skip(4).forEach(s -> System.out.println(s));//4 就是跳过前面四个元素 System.out.println("========================="); list.stream().limit(6).skip(3).forEach(s -> System.out.println(s)); /* 因为Stream流只能使用一次 使用都是链式编程 */
distinct去重 依赖hashcode和equals方法 concat 合并a,b流为一个流
/* stream流方法 */ ArrayList<String> list1 = new ArrayList<>(); Collections.addAll(list1,"张无忌","张无忌","张无忌","周芷若","赵敏","张强","张三丰","张翠山","张良","王二麻子","谢广坤"); ArrayList<String> list2 = new ArrayList<>(); Collections.addAll(list2,"周芷若","赵敏"); //distinct 元素去重 依赖(hashcode和equals方法 list1.stream().distinct().forEach(s -> System.out.println(s)); //如果是自己写的类的对象 记得重写hashcode和equals方法 底层通过HashSet实现 System.out.println("=========================="); //concat合并a,b两个流为一个流 Stream.concat(list1.stream(),list2.stream()).forEach(s -> System.out.println(s));
map 转换流中数据类型
/* map 转换流中的数据类型 */ ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"张无忌-15","周芷若-14","赵敏-13","张强-20", "张三丰-100","张翠山-40","张良-45","王二麻子-35","谢广坤-37"); //只获取里面的年龄 //第一个类型表示流中原本的数据类型 第二个表示要转换后的类型 /*list.stream().map(new Function<String, Integer>() { //形参s表示流中的每一个数据 返回值表示转换之后的数据 @Override public Integer apply(String s) { String[] arr = s.split("-");//安- 切割 String ageString = arr[1]; int age = Integer.parseInt(ageString); return age; }//当map方法执行完毕后 下面里面的s依次表示流中的每一个数据 这个数据就是整数 }).forEach(s-> System.out.println(s)); */ list.stream().map(s->Integer.parseInt(s.split("-")[1])) .forEach(s-> System.out.println(s));
Stream流的终结方法
forEach 遍历
count 统计
toArray 收集数据 放入数组
collect 收集数据 放入集合
/* stream流 Collect 收集流中数据 放入集合(List,set,Map) */ ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"张无忌-男-15","张无忌2-男-15","周芷若-女-14","赵敏-女-16","张强-男-34", "张三丰-男-100","张翠山-男-45","张良-男-25","王二麻子-男-41","谢广坤-男-29"); /* 收集到List集合 需求:把男收集起来 */ List<String> collectList = list.stream() .filter(s -> "男".equals(s.split("-")[1])) .collect(Collectors.toList()); System.out.println(collectList); System.out.println("==============================="); /* 收集到set集合 set集合会自动去重 需求:把男收集起来 */ Set<String> collectSet = list.stream() .filter(s -> "男".equals(s.split("-")[1])) .collect(Collectors.toSet()); System.out.println(collectSet); System.out.println("==============================="); /* 收集到Map集合 需求:把男收集起来 注意键不能重复 键:姓名 值:年龄 */ Map<String, Integer> map = list.stream() .filter(s -> "男".equals(s.split("-")[1])) /* toMap: 参数1 键的生成规则 参数二 值的生成规则 参数1: Function泛型1:流中数据类型 泛型2:Map集合中数据类型 方法apply形参:依次表示流里面的每一个数据 方法体 生成键的代码 返回值 已经生成的键 */ .collect(Collectors.toMap(new Function<String, String>() {//第一个new表示键的规则 第一个参数是流中数据类型 第二个是Map中的数据类型 @Override public String apply(String s) { return s.split("-")[0]; } }, new Function<String, Integer>() {//第二个new 表示值的规则 @Override public Integer apply(String s) { return Integer.parseInt(s.split("-")[2]); } })); System.out.println(map); System.out.println("==============================="); //lambda表达式写法 Map<String, Integer> map1 = list.stream() .filter(s -> "男".equals(s.split("-")[1])) .collect(Collectors.toMap( s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[2]) )); System.out.println(map1);
练习:
数据过滤
/* 定义一个集合 并添加一些整数 1到10 过滤奇数 只留下偶数 并保存结果 */ ArrayList<Integer> list = new ArrayList<>(); Collections.addAll(list,1,2,3,4,5,6,7,8,9,10); System.out.println(list); List<Integer> collect = list.stream().filter(s -> s % 2 == 0) .collect(Collectors.toList()); System.out.println(collect);
数据操作
一:
/* 练习 创建一个ArrayList集合 添加数据 保留年龄大于等于24 并将结果收集到Map集合 姓名为键 年龄为值 */ ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"张三,23","李四,24","王五,25"); System.out.println(list); Map<String, Integer> collect = list.stream().filter(s -> Integer.parseInt(s.split(",")[1])>=24).collect(Collectors.toMap( s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1]) )); System.out.println(collect);
二:
/* 根据下面的两个集合完成: 1.男演员只要名字为3个字的前两人 2.女演员只要姓杨的,并且不要第一个 3.把过滤后的男演员和女演员姓名合并在一起 4.将上一步的演员姓名封装成Actor对象 5.将所有的演员对象都保存到List集合 Actor :属性: name age */ ArrayList<String> manlist = new ArrayList<>(); ArrayList<String> womenlist = new ArrayList<>(); Collections.addAll(manlist,"蔡徐坤,24","耶和华,23","刘不甜,22","吴签,24","谷加,30","肖木木,27"); Collections.addAll(womenlist,"赵小眼,35","杨岩,36","高原因,43","张天天,31","刘师,35","杨大大,33"); //1.男演员只要名字为3个字的前两人 Stream<String> manStream = manlist.stream().filter(s -> s.split(",")[0].length() == 3).limit(2); System.out.println("=============================="); //2.女演员只要姓杨的,并且不要第一个 Stream<String> womenStream = womenlist.stream().filter(s -> s.split(",")[0].startsWith("杨")).skip(1); //3.把过滤后的男演员和女演员姓名合并在一起 System.out.println("=============================="); // Stream.concat(manStream,womenStream).map(new Function<String, Actor>() { // @Override // public Actor apply(String s) { // String name = s.split(",")[0]; // int age = Integer.parseInt(s.split(",")[1]); // Actor actor = new Actor(name,age); // return actor; // } // }).forEach(s-> System.out.println(s)); List<Actor> list = Stream.concat(manStream, womenStream) .map(s -> new Actor(s.split(",")[0], Integer.parseInt(s.split(",")[1]))) .collect(Collectors.toList()); System.out.println(list);