该笔记基于b站视频完成Java-Stream流从入门到精通
什么是Stream流
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果
Stream流的作用:结合了Lambda表达式,简化了集合、数组的操作
Stream流的使用步骤
- 先得到一条Stream流,并把数据放上去
- 利用Stream流中的API进行各种操作
- 中间方法:过滤、转换 方法调用完毕之后、还可以调用其他方法
- 终结方法:统计、打印 最后一步,调用完毕之后,不能再调用其他方法
把数据放到Stream流上去
| 获取方式 |
方法名 |
说明 |
| 单例集合 |
default Stream stream() |
Collection中的默认方法 |
| 双列集合 |
无 |
无法直接使用Stream流 |
| 数组 |
public static Stream stream (T… values) |
Arrays工具类中的静态方法 |
| 一堆零散的数据 |
public static Stream of (T… values) |
Stream接口中你的静态方法 |
单例集合获取Stream流
1 2 3 4 5
| ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "a", "b", "b", "d");
list.stream().forEach(s -> System.out.println(s));
|
双列集合获取Stream流
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| HashMap<String, Integer> hm = new HashMap<>();
hm.put("a",1); hm.put("b",2); hm.put("c",3); hm.put("d",4);
hm.keySet().stream().forEach(s -> System.out.println(s)); hm.values().stream().forEach(x -> System.out.println(x));
hm.entrySet().stream().forEach(y -> System.out.println(y));
|
数组获取Stream流
1 2
| int[] arr = {1,2,3,4,5}; Arrays.stream(arr).forEach(s -> System.out.println(s));
|
一堆零散数据获取Stream流
1 2 3
| Stream(1,2,3,4,5)..forEach(s -> System.out.println(s)); Stream("a","b","c")..forEach(s -> System.out.println(s));
|
Stream流的中间方法
| 名称 |
说明 |
| Stream filter(Predicate<? super T> predicate) |
过滤 |
| Stream limit(long maxSize) |
获取前面几个元素 |
| Stream skip(long n) |
跳过前面几个元素 |
| Stream distinct() |
元素去重,依赖于hashCode和equals方法 |
| static Stream concat(Stream a, Stream b) |
合并a和b两个流为一个流 |
| Stream map(Function<T, R> mapper) |
转换流中的数据类型 |
注意:
- 中间方法,返回新的Stream流,原来的Stream流只能使用一次,建议使用链式编程
- 修改Stream流中的数据,不会影响原来集合或者数据中的数据
filter、limit、skip
1 2 3 4 5 6 7 8 9 10 11 12
| ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤");
list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
list.stream().limit(6).skip(3).forEach(s -> System.out.println(s));
list.stream().skip(3).limit(3).forEach(s -> System.out.println(s));
|
distinct、concat
1 2 3 4 5 6 7 8 9 10 11
| ArrayList<String> list1 = new ArrayList<>(); Collections.addAll(list1, "a", "a", "a", "b", "b", "c", "d", "e", "f");
list1.stream().distinct().forEach(s -> System.out.println(s));
ArrayList<String> list1 = new ArrayList<>(); Collections.addAll(list1, "g", "h"); Stream.concat(list1.stream(), list2.stream());
|
map
1 2 3 4 5 6 7
| ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "张无忌-15", "周芷若-18", "赵敏-17", "张强-31", "张三丰-23", "张翠山-15", "张良-20", "王二麻子-25", "谢广坤-40");
list.stream() .map(s -> Integer.parseInt(s.split("-")[1])) .forEach(s -> System.out.println(s));
|
Stream流的终结方法
| 名称 |
说明 |
| void forEach(Consumer action) |
遍历 |
| long count() |
统计 |
| toArray() |
收集流中的数据,放到数组中 |
| collect(Collector collector) |
收集流中的数据,放到集合中 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰", "张翠山", "张良", "王二麻子", "谢广坤");
list.stream().forEach(a -> System.out.println(s));
long count = list.stream().filter(s -> s.startsWith("张")).count(); System.out.println(count);
Object[] arr1 = list.stream().toArray();
String[] arr2 = list.stream().toArray(value -> new String[value]);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ArrayList<String> list = new ArrayList<>(); Collections.addAll(list, "张无忌-男-15", "周芷若-女-18", "赵敏-女--17", "张强-男-31", "张三丰-男-23", "张翠山-女-15", "张良-男-20", "王二麻子-男-25", "谢广坤-男-40");
List<String> newList = list.stream() .filter(s -> "男".equals(s.split("-")[1])) .collect(Collectors.toList());
List<String> newSet = list.stream() .filter(s -> "男".equals(s.split("-")[1])) .collect(Collectors.toSet());
Map<String, Integer> newMap = list.stream() .filter(s -> "男".equals(s.split("-")[1])) .collect(Collectors.toMap( s -> s.split("-")[0], s -> Integer.parseInt(s.split("-")[3]) ));
|
总结
Stream流的作用
结合了Lambda表达式,简化集合、数组的操作
Stream流的使用步骤
- 获取Stream流对象
- 使用中间方法处理数据
- 使用终结方法处理数据
如何获取Stream流对象
- 单列集合:Collection中的默认方法Stream
- 双列集合:不能直接获取,要转为单列集合
- 数组:Arrays工具类中的静态方法Stream
- 零散的数据:Stream接口中的静态方法of
常见方法
- 中间方法:filter、limit、skip、distinct、concat、map
- 终结方法:forEach、count、collect
练习题
定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
过滤奇数,只留下偶数
并将结果存下来
1 2 3 4 5 6
| ArrayList<Integer> list = new ArrayList<>(); Collections.addAll(list,1,2,3,4,5,6,7,8,9,10); List<Integer> collect = list.stream() .filter(s -> s % 2 == 0) .collect(Collectors.toList()); System.out.println(collect);
|
创建一个ArrayList集合,并添加一下字符串,字符串中前面是姓名,后面是年龄
“张三,23”
“李四,24”
“王五,25”
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
1 2 3 4 5 6 7 8
| ArrayList<String> list = new ArrayList<>(); Collections.addAll(list,"张三,23","李四,24","王五,25"); Map<String, Integer> map = 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(map);
|
现在有两个ArrayList集合,
第一个集合中:存储6名男演员的名字和年龄,第二个集合中:存储6名女演员的名字和年龄
姓名和年龄中间用逗号隔开。如:”张三,23”
要求完成如下的操作:
- 男演员只要名字为3个字的前两人
- 女演员只要姓杨的,并且不要第一个
- 把过滤后的男演员姓名和女演员姓名合并到一起
- 将上一步的演员信息封装成Actor对象
- 将所有的演员对象都保存到List集合中
演员类属性: name, age
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ArrayList<String> manList = new ArrayList<>(); Collections.addAll(manList,"蔡坤坤,24","叶齁咸,23","刘不甜,22","吴签,24","谷嘉,30","肖凉凉,27"); ArrayList<String> womenList = new ArrayList<>(); Collections.addAll(womenList,"赵小颖,35","杨颖,36","高圆圆,43","张天天,31","刘诗,35","杨小幂,33");
Stream<String> menStream = manList.stream().filter(s -> s.split(",")[0].length() == 3).limit(2);
Stream<String> womenStream = womenList.stream().filter(s -> s.split(",")[0].startsWith("杨")).skip(1);
List<Actor> actorList = Stream.concat(menStream, womenStream) .map(s -> new Actor(s.split(",")[0] , Integer.parseInt(s.split(",")[1]))) .collect(Collectors.toList()); System.out.println(actorList);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class Actor { private String name; private int age;
public Actor() { }
public Actor(String name, int age) { this.name = name; this.age = age; }
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; }
@Override public String toString() { return "Actor{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
|