第一章 简单体验一下Stream流
- 我们使用Stream流的方式,可以用来遍历集合,对集合中的数据进行过滤等,Stream流是在jdk1.8之后出现
- 代码示例
public class DemoTextStream{ public static void main(String[] args){ // 创建一个list集合,用来存储姓名 List<String> list = new ArrayList<>(); list.add("李冰冰"); list.add("彭于晏"); list.add("李易峰"); list.add("李沁"); list.add("王思聪"); // 对List集合的元素进行过滤,只要以张开头的元素,存储到一个新的集合中 // 对listA集合进行过滤,只要姓名长度为三的人 // 遍历集合 list.Stream() .filter(name->name.startsWith("李")) .filter(name->name.length()==3) .foreach(name->System.out.println(name)); } }
流式思想的概述
对于流式思想,可以把它想象成工厂的“流水线”。通过一系列的加工、过滤得到最后的产品
何为Stream
- Stream流实际上是一个来自数据源的元素队列
- Java中的Stream并不会存储元素,而是按需计算
- Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
第二章 获取Stream流的方式
- java.util.stream.Stream<T>
是java中新加入的最常用的流接口
获取流的两种方式
- 所有的collection集合都可以通过stream默认方法获取流
Stream接口的静态方法of可以获取数组对应的流
static<T> Stream<T> of(T...values)
参数是一个可变参数,可以通过这个方法传递一个数组代码演示:
public class DemoMethodAcq{ public static void main(String[] args){ //把集合转换为Stream流 List<String> list = new Arraylist<String>(); Stream<String> str = list.stream(); Set<String> set = new HashSet<>(); Stream<String> stream2 = set.stream(); Map<String,String> map = new HashMap<>(); //获取键,存储到一个Set集合中 Set<String> keyset =map.keyset(); Stream<String> Stream3 = keyset.stream(); //获取值,存储到一个Collection集合中 Collection<String> values = map.values(); Stream<String> stream4 = values.stream(); //获取键值对 Set<Map.Entry<String,String>> entries = map.entries(); Stream<Map.Entry<String,String>> stream5 = entries.stream(); //把数组转换为Stream流 Stream<Integer> stream6 = Stream.of(1,2,3,4,5); //可变参数可以传递数组 Integer[] arr = {1,2,3,4,5}; Stream<Integer> stream7 = Stream.of(arr); String[] arr2 ={"a","bb","ccc"}; Stream<String> stream8 = Stream.of(arr2); } }
第三章 Stream流的常用方法
流模型的操作被分为两种方法:
1.延迟方法: 返回值类型仍然是Stream
接口自身类型的方法,因此支持链式调用(除了延时方法其他均为终结方法)
2.终结方法: 返回值类型不在是Stream
接口自身类型的方法,因此不在支持类似StringBuilder
那样的链式调用(终结方法包括count
和forEach
方法)1、forEach方法(逐一处理)
- 首先,此方法非for循环的for-each循环方法
- 其标准格式为:
void forEach(Consumer<? suoer T> action);
- forEach方法是通过接收一个Consumer接口函数,会使每一个流元素交给该函数处理
- 可以简记为:
- forEach是用来遍历流数据的
- 它是一个终结方法,遍历之后就不能继续调用Stream流中的其他方法
- 代码演示:
public class Demo_forEach{ public static void main(String[] args){ //获取一个Stream流 Stream<String> stream = Stream.of("张三","李四","w王五","赵六"); //使用Stream流中的方法forEach对Stream流中的数据进行遍历 stream.forEach((String name)-> { System.out.println(name); }); /* 简写可以这样: stream.forEach(name-> System.out.println(name) ); */ } }
2、filter方法(过滤)
- 使用
filter
方法可以将一个流转换成另一个字节流Stream<T> filter(Predicate<? super T> predicate);
- 此接口接收一个
Predicate
函数式接口参数作为筛选条件,即:boolean test(T t);
- 该方法是Predicate接口中的一个抽象方法
public class Demo_filter{ public static void main(String[] args){ //创建一个Stream流 Stream<String> stream = Stream.of("李冰冰","李易峰","彭于晏","李沁","王思聪"); //对Stream流中的元素进行过滤,筛选出姓“李”的人 Stream<String> stream2 = stream.filter((String name)->{ return name.startWith("李"); }); //遍历stream2 stream.forEach(name-> System.out.println(name)); } }
- Stream流属于管道流,只能被消费一次
- 第一次Stream流调用完毕后,数据会流到下一个Stream上
- 此时第一个Stream流消费完毕,就会关闭
3、map方法(映射)
- map方法是将流中的元素映射到另一个流中,可以使用map方法
<R> Stream<R> map{Function<? super T,? extends R> mapper};
- 该接口需要一个
Function
的函数式接口参数 - 使用的是Function接口的抽象方法:
R apply(T t);
- 该接口需要一个
- 代码演示:
public class Demo_map{ public static void main(String[] args){ //获取一个String类型的Stream流 Stream<String> stream = Stream.of("1","2","3","4","5"); //使用map方法,把字符串类型的整数,转换(映射)到Integer类型的整数 Stream<Integer> stream2 = stream.map((String s)->{ return Integer.parseInt(s); }); //遍历stream2 stream2.forEach(i-> System.out.println(i)); } }
4、count方法(统计个数)
- Stream流通过
count
方法来对流中的元素进行统计,即:long count();
- count方法是一个终结方法,返回值是一个Long类型的整数,不能再继续调用Stream流中的其他方法
代码示例:
import java.util.stream.Stream; public class Demo_count{ public static void main(String[] args){ Stream<String> stream = Stream.of("李冰冰","李易峰","王思聪"); Stream<String> result = stream.filter(s-> s.startWith("李")); System.out.println(result.count());//输出为2 } }
5、limit方法(截取使用前几个)
```java Stream<T> limit(long maxSize);
- 参数是一个Long类型,如果集合当前长度大于参数则进行截取,否则不操作
- limit方法是一个延迟方法,返回的是一个新的流,可以调用Stream流的其他方法
- 代码展示:
public class Demo_limit{ public static void main(String[] args){ //获取一个Stream流 String[] arr = {"李冰冰","李易峰","王思聪"}; Stream<String> stream = Stream.of(arr); //使用Limit对Stream流中的元素进行截取,只要前2个元素 Stream<String> stream2 =stream.limit(2); //遍历stream2 stream2.forEach(name-> System.out.println(name)); } }
6、skip方法(跳过前几个)
- 如果需要跳过前几个元素,可以使用
skip
方法进行截取流,即:Stream<T> skip(long n);
- 若要跳过的元素个数n大于流中元素的个数,则会截取流,得到一个长度为0的空流(新流)
- 代码展示:
public class Demo_limit{ public static void main(String[] args){ //获取一个Stream流 String[] arr = {"李冰冰","李易峰","王思聪"}; Stream<String> stream = Stream.of(arr); //使用skip跳过前2个元素 Stream<String> stream2 =stream.skip(2); //遍历stream2 stream2.forEach(name-> System.out.println(name)); } }
7、concat方法(组合)
如果有两个流,需要合并为一个流,则需要使用
concat
静态方法,即:static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b);
备注:这是一个静态方法,与
java.lang.String
当中的concat
方法不同- 代码展示:
```java
import java.util.stream.Stream;
public class Demo_concat{
public static void main(String[] args){ Stream<String> streamA = Stream.of("李冰冰"); Stream<String> streamB = Stream.of("李易峰"); Stream<String> result = Stream.concat(streamA,streamB); }
}
```- 代码展示: