1.什么是Stream
Stream Api对集合数据进行操作,就类似于使用sql执行的数据库查询
Stream是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列.
集合讲的是数据,Stream讲的是计算
注意:
- Stream自己不会存储元素
- Stream不会改变源对象.相反,他会返回一个持有结果的新Stream
- Stream操作是延迟执行的,意味着他们会等到需要结果的时候才执行
1.1 Stream的操作三步骤
1.创建Stream
一个数据源(如:集合、数组),获取一个流2.中间操作
一个中间操作链,对数据源的数据进行处理3.终止操作
一旦执行了终止操作,就执行中间操作链
,并产生结果,之后,不会再被使用
2.Stream实例化
2.1 通过集合
- Stream<E> stream(): 返回一个顺序流
- Stream<E> parallelStream(): 返回一个并行流
public void test() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小张", 32));
list.add(new Person("小王", 12));
// default Stream<E> Stream() 返回一个顺序流
Stream<Person> stream = list.stream();
// default Stream<E> parallelStream() 返回一个并行流
Stream<Person> parallelStream = list.parallelStream();
}
2.2 通过数组
@Test
public void test2() {
int[] arr = {1, 2, 3, 4, 5, 6};
// 调用Arrays类的Stream<T> stream(T[] array) 返回一个流
IntStream stream = Arrays.stream(arr);
Person p1 = new Person("小张", 32);
Person p2 = new Person("小王", 12);
Person[] personArr = new Person[]{p1, p2};
Stream<Person> stream1 = Arrays.stream(personArr);
}
2.3 通过Stream类的静态方法
@Test
public void test3() {
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
Stream<Long> longStream = Stream.of(1L, 2L, 3L, 4L, 5L);
Stream<Double> doubleStream = Stream.of(1.0, 2.0, 3.0, 4.0, 5.0);
Stream<String> stringStream = Stream.of("1", "2", "3", "4", "5");
Stream<Person> personStream = Stream.of(new Person("小张", 32), new Person("小王", 12));
}
2.4 创建无限流
- Stream<T> iterate(final T seed, final UnaryOperator<T> f)
final T seed:初始值
final UnaryOperator<T> f:函数式接口,参数和返回值都是一个类型的
// 遍历从0开始的前10个偶数
@Test
public void test4() {
Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);
}
- Stream<T> generate(Supplier<T> s)
Supplier<T> s:无参数,返回类型为任意类型的函数式接口
// 生成
Stream.generate(Math::random).limit(10).forEach(System.out::println);
3.Stream的中间操作
多个中间操作可以连接形成一个流水线
,除非流水线上触发终止操作,否则中间操作不会执行任何处理
!而在终止操作时,一次性全部处理,称为"惰性求值"
3.1 筛选和切片
- filter(Predicate p)
接收lambda,从流中排除某些元素 - distinct()
筛选,通过流所生成的元素 hashCode()和equals去除重复元素 - limit(long maxSize)
截断流,使其元素不超过给定数量 - skip(long n)
跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
@Test
public void test4() {
getStream().filter(t -> t.age >20).forEach(System.out::println);
getStream().limit(3).forEach(System.out::println);
getStream().skip(2).forEach(System.out::println);
// 需要重写Person类的hashCode()和equals()方法
getStream().distinct().forEach(System.out::println);
}
public static Stream<Person> getStream() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小张", 32));
list.add(new Person("小王", 12));
list.add(new Person("小李", 16));
return list.stream();
}
3.2 映射
- map(Function<? super T, ? extends R> mapper)
接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射为一个新的元素 - <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
接收一个函数作为参数,将流中每个值转换成另一个流,然后将所有流连成一个流
@Test
public void test5() {
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
// 获取年龄大于20岁的人的姓名
getStream().filter(t -> t.age > 20).map(t -> t.name).forEach(System.out::println);
// 使用map
Stream<Stream<Character>> streamStream = list.stream().map(StreamApi::fromStringToStream);
streamStream.forEach(t -> {
t.forEach(System.out::println);
System.out.println("---");
});
// 使用flatMap
Stream<Character> characterStream = list.stream().flatMap(StreamApi::fromStringToStream);
characterStream.forEach(System.out::println);
}
public static Stream<Character> fromStringToStream(String str) {
ArrayList<Character> list = new ArrayList<>();
for (Character c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
public static Stream<Person> getStream() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小张", 32));
list.add(new Person("小王", 12));
list.add(new Person("小李", 16));
return list.stream();
}
3.3 排序
@Test
public void test6() {
List<Integer> list = Arrays.asList(12, 43, 65, 34, 87, 0, -98);
// 自然排序
list.stream().sorted().forEach(System.out::println);
// 使用定制排序
getStream().sorted((o1, o2) -> o2.age - o1.age).forEach(System.out::println);
}
public static Stream<Person> getStream() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小张", 32));
list.add(new Person("小王", 12));
list.add(new Person("小李", 16));
return list.stream();
}
4.Stream的终止操作
4.1 匹配和查找
- boolean allMatch(Predicate<? super T> predicate): 检查是否匹配所有元素
- boolean anyMatch(Predicate<? super T> predicate): 检查是否至少匹配一个元素
- boolean noneMatch(Predicate<? super T> predicate): 检查是否没有匹配的元素
- Optional<T> findFirst(): 返回第一个元素
- Optional<T> findAny(): 返回当前流中任意元素(在parallelStream下使用)
- long count(): 返回流中元素的总个数
- Optional<T> max(Comparator<? super T> comparator): 返回流中最大值
- Optional<T> min(Comparator<? super T> comparator): 返回流中最小值
- void forEach(Consumer<? super T> action): 内部迭代
@Test
public void test6() {
// 是否所有人的年龄都大于18岁
boolean b1 = getStream().allMatch(t -> t.age > 18);
System.out.println(b1);
// 是否存在大于18岁的人
boolean b2 = getStream().anyMatch(t -> t.age > 18);
System.out.println(b2);
// 是否所有人的年龄都不大于18
boolean b3 = getStream().noneMatch(t -> t.age > 18);
System.out.println(b3);
// 返回第一个元素
Optional<Person> first = getStream().findFirst();
System.out.println(first);
// 返回当前流中任意元素(在parallelStream下使用)
Optional<Person> any = getStream().findAny();
System.out.println(any);
// 返回流中元素的总个数
long count = getStream().count();
System.out.println(count);
// 返回流中最大值
Optional<Person> max = getStream().max((o1, o2) -> Integer.compare(o1.age, o2.age));
System.out.println(max);
// 返回流中最小值
Optional<Person> min = getStream().min((o1, o2) -> Integer.compare(o1.age, o2.age));
System.out.println(min);
}
public static Stream<Person> getStream() {
ArrayList<Person> list = new ArrayList<>();
list.add(new Person("小明", 25));
list.add(new Person("小李", 16));
list.add(new Person("小张", 32));
list.add(new Person("小王", 12));
return list.stream();
}
4.2 归约
- T reduce(T identity, BinaryOperator<T> accumulator); 可以将流中元素反复结合起来,得到一个值
- Optiona\l reduce(BinaryOperator<T> accumulator); 可以将流中元素反复结合起来,得到一个值
public void test6() {
// 计算1~10的自然数的总和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer reduce = list.stream().reduce(0, Integer::sum);
System.out.println(reduce);
// 计算年龄的总和
Stream<Integer> ageStream = getStream().map(t -> t.age);
Optional<Integer> ageSum = ageStream.reduce(Integer::sum);
System.out.println(ageSum);
}
4.3 收集
- <R, A> R collect(Collector<? super T, A, R> collector);
// 将年纪大于20岁的人,存入一个集合中
List<Person> collect = getStream().filter(t -> t.age > 20).collect(Collectors.toList());
System.out.println(collect);