参考资料
https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/
https://www.cnblogs.com/aoeiuv/p/5911692.html
http://www.java2s.com/Tutorials/Java/Java_Stream/index.htm
https://blog.csdn.net/qq_28410283/article/details/80633292
流的操作类型
流的操作类型分为两种:
Intermediate
一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。
这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。
map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
Terminal
一个流只能有一个 terminal 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。
Terminal 操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个 side effect。
forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
还有一种操作被称为short-circuiting。用以指:
- 对于一个 intermediate 操作,如果它接受的是一个无限大(infinite/unbounded)的 Stream,但返回一个有限的新 Stream。
- 对于一个 terminal 操作,如果它接受的是一个无限大的 Stream,但能在有限的时间计算出结果。
当操作一个无限大的 Stream,而又希望在有限时间内完成操作,则在管道内拥有一个 short-circuiting 操作是必要非充分条件。
anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit
流只有在进行Terminal或者个别Short-circuiting之后才会开始执行
流无法复用,用完即销毁
流的分类
特殊流
专门用于处理基本类型,int,double,long
IntStream,DoubleStream,LongStream
对象流
处理对象类型
流常用方法
import org.junit.Test;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import lombok.Data;
import lombok.experimental.Accessors;
public class StreamTest {
/** 生成连续数字,含头不含尾*/
@Test
public void testRange() {
IntStream.range(0, 10).forEach(System.out::println);
}
/** 生成连续数字,含头含尾*/
@Test
public void testRangeClosed() {
IntStream.rangeClosed(0, 10).forEach(System.out::println);
}
/** 生成从0开始递增3的前10位数字*/
@Test
public void testIterate() {
IntStream.iterate(0, e -> e + 3).limit(10).forEach(System.out::println);
}
/** 生成从0开始递增3,跳过前10位后的前5位数字*/
@Test
public void testSkip() {
IntStream.iterate(0, e -> e + 3).skip(10).limit(5).forEach(System.out::println);
}
/** 生成当前日期开始,递增1天的前5位时间*/
@Test
public void testDateIterate() {
Stream.iterate(LocalDate.now(), e -> e.plusDays(1)).limit(5).forEach(System.out::println);
}
/** 基本类型转包装类型*/
@Test
public void testBoxed() {
List<Integer> collect = IntStream.range(10, 20).boxed().collect(Collectors.toList());
System.out.println(collect);
}
/** 基本类型装对象类型*/
@Test
public void testMapToObj() {
List<TestPo> collect =
IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e)).collect(Collectors.toList());
System.out.println(collect);
}
/** 统计*/
@Test
public void testCount() {
long count = IntStream.range(0, 10).count();
System.out.println(count);
}
/** 去重*/
@Test
public void testDistinct() {
IntStream.range(0, 10).map(e -> e % 2).forEach(System.out::println);
IntStream.range(0, 10).map(e -> e % 2).mapToObj(e->new TestPo().setOrder(e)).distinct().forEach(System.out::println);
}
/** 求和*/
@Test
public void testSum() {
int sum = IntStream.range(0, 10).sum();
System.out.println(sum);
}
/** 过滤,保留filter中返回值为true的属性*/
@Test
public void testFilter() {
IntStream.range(0, 10).filter(e -> e >= 5).forEach(System.out::println);
}
/** 聚合操作*/
@Test
public void testReduce() {
BigDecimal reduce =
DoubleStream.iterate(1, e->e+1).limit(10).mapToObj(BigDecimal::valueOf).reduce(BigDecimal.ZERO,
BigDecimal::add);
System.out.println(reduce.toPlainString());
}
/** 把input Stream 中的层级结构扁平化,就是将最底层元素抽出来放到一起,返回对象必须是Stream*/
@Test
public void testFlatMap() {
List<Integer> collect = IntStream.rangeClosed(0, 10).boxed().collect(Collectors.toList());
List<Integer> collect1 = IntStream.rangeClosed(5, 15).boxed().collect(Collectors.toList());
List<Integer> collect2 = IntStream.rangeClosed(10, 20).boxed().collect(Collectors.toList());
List<List<Integer>> list = new ArrayList<>();
list.add(collect);
list.add(collect1);
list.add(collect2);
System.out.println(list);
List<Integer> collect3 = list.stream().flatMap(e -> e.stream()).collect(Collectors.toList());
System.out.println(collect3);
}
/** 对每个元素执行操作并返回一个新的 Stream*/
@Test
public void testPeek() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e).setName("test" + e))
.collect(Collectors.toList());
System.out.println(collect);
List<TestPo> collect1 = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e).setName("test" + e))
.peek(e -> e.setOrder(e.getOrder() + 10)).collect(Collectors.toList());
System.err.println(collect1);
}
/** 聚合为map*/
@Test
public void testToMap() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e).setName("test" + e))
.collect(Collectors.toList());
Map<String, TestPo> collect1 = collect.stream().collect(Collectors.toMap(e -> e.getName(), e -> e));
System.out.println(collect1);
}
/** 按指定属性分组*/
@Test
public void testGroupingBy() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e % 3).setName("test" + e))
.collect(Collectors.toList());
Map<Integer, List<TestPo>> collect1 = collect.stream().collect(Collectors.groupingBy(e -> e.getOrder()));
System.out.println(collect1);
}
/** 按指定属性分组后,对每组元素进行操作*/
@Test
public void testGroupingByExpand() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e % 3).setName("test" + e))
.collect(Collectors.toList());
Map<Integer, Set<String>> collect1 = collect.stream().collect(
Collectors.groupingBy(e -> e.getOrder(), Collectors.mapping(e -> e.getName(), Collectors.toSet())));
System.out.println(collect1);
}
/** 按指定属性分组后,对每组元素进行操作*/
@Test
public void testGroupingByExpand1() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e % 3).setName("test" + e))
.collect(Collectors.toList());
Map<Integer, Long> collect1 =
collect.stream().collect(Collectors.groupingBy(e -> e.getOrder(), Collectors.counting()));
System.out.println(collect1);
}
/** 根据判断条件对数据进行分割,满足条件的key为true*/
@Test
public void testPartitioningBy() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e % 3).setName("test" + e))
.collect(Collectors.toList());
Map<Boolean, List<TestPo>> collect1 =
collect.stream().collect(Collectors.partitioningBy(e -> e.getOrder() > 1));
System.out.println(collect1);
}
/** 排序操作*/
@Test
public void testSort() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e % 3).setName("test" + e))
.collect(Collectors.toList());
System.out.println(collect);
collect.sort(Comparator.comparing(e -> e.getOrder()));
System.out.println(collect);
}
/** 排序操作,可以多字段排序,可指定排序器,可控制null值处理及正序倒叙*/
@Test
public void testSorted() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e % 3).setName("test" + e))
.sorted(Comparator.comparingInt(e -> e.getOrder())).collect(Collectors.toList());
System.out.println(collect);
}
/** 并行流(fork join)*/
@Test
public void testParallel() {
IntStream.range(0, 10).parallel().boxed().forEach(System.out::println);
}
/** 并行流(fork join)*/
@Test
public void testParallel1() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e).setName("test" + e))
.collect(Collectors.toList());
collect.parallelStream().map(e -> e.getOrder()).forEach(System.out::println);
collect.parallelStream().map(e -> e.getOrder()).forEachOrdered(System.err::println);
}
/** 全部不匹配*/
@Test
public void testNoneMatch() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e).setName("test" + e))
.collect(Collectors.toList());
System.out.println(collect.stream().noneMatch(e -> e.getOrder() > 8));
}
/** 任意一个匹配*/
@Test
public void testAnyMatch() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e).setName("test" + e))
.collect(Collectors.toList());
System.out.println(collect.stream().anyMatch(e -> e.getOrder() > 8));
}
/** 全部匹配*/
@Test
public void testAllMatch() {
List<TestPo> collect = IntStream.range(0, 10).mapToObj(e -> new TestPo().setOrder(e).setName("test" + e))
.collect(Collectors.toList());
System.out.println(collect.stream().allMatch(e -> e.getOrder() > 8));
}
@Data
@Accessors(chain = true)
public static class TestPo {
private Integer order;
private String name;
private TestPo1 po1;
@Data
public static class TestPo1{
private String age;
}
}
}