Java中的stream流以及相关的操作
流(Stream)到底是什么呢?
- 是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
- “集合讲的是数据,流讲的是计算!
注意:
①Stream自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
③Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
stream的三个操作
创建Stream
一个数据源(如:集合、数组),获取一个流
中间操作
一个中间操作链,对数据源的数据进行处理
终止操作(终端操作)
一个终止操作,执行中间操作链,并产生结果
创建流的操作
@Test
public void test1() {
//第一种,通过collection系列集合中提供的stream()或者parallelStream()方式
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
//第二种,通过Array中的静态方式stream()获取数组的流
Student[] stu = new Student[10];
Stream<Student> stream2 = Arrays.stream(stu);
//第三种,通过Stream中的静态方法of()
Stream<String> stream3 = Stream.of("A","b","dd");
//第四种,创建无限流
//迭代
Stream.iterate(0, (x)-> x + 10)
.limit(10)
.forEach(System.out::println);
//生成
Stream.generate(() -> Math.random())
.limit(10)
.forEach(System.out::println);
}
流的Intermediate方法(中间操作)
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。
filter(Predicate) : 将结果为false的元素过滤掉
limit(n) :保留前n个元素
skip(n) :跳过前n个元素
distinct() :剔除重复元素,通过hashCode和equals方式去重,需要重写该方法
map(fun): 转换元素的值,作用于所有元素上,匹配相应的元素。可以用方法引元或者lambda表达式
@Test
public void test2() {
List<String> list = Arrays.asList("aa","bb","cc","dd","ee","FF");
list.stream()
.map((str) -> str.toUpperCase())
.forEach(System.out::println);
}
flatMap(fun): 作用于嵌套型的流
例如:返回值为Stream<Stream<Character.>>类型的流中嵌套着流,使用flatMap
sorted(): 将Comparable元素v的流排序
sorted(Comparator): 将流元素按Comparator排序
peek(fun) :流不变,但会把每个元素传入fun执行,可以用作调试
流的Terminal方法(终结操作)
查找与匹配操作
max(Comparator)
min(Comparator)
count()
findFirst():返回第一个元素
findAny(): 返回任意元素
anyMatch(Predicate) :任意元素匹配时返回true
allMatch(Predicate): 所有元素匹配时返回true
noneMatch(Predicate) :没有元素匹配时返回true
归约操作
reduce(fun): 从流中计算某个值,接受一个二元函数作为累积器,从前两个元素开始持续应用它,累积器的中间结果作为第一个参数,流元素作为第二个参数
reduce(a, fun): a为起始值,作为累积器的起点
计算集和中的值
@Test
public void test3() {
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer reduce = list.stream()
.reduce(0,(x,y)-> x + y );
System.out.println(reduce);//55
}
reduce(a, fun1, fun2) :与二元变形类似,并发操作中,当累积器的第一个参数与第二个参数都为流元素类型时,可以对各个中间结果也应用累积器进行合并,但是当累积器的第一个参数不是流元素类型而是类型T的时候,各个中间结果也为类型T,需要fun2来将各个中间结果进行合并
收集操作
iterator()
forEach(fun)
forEachOrdered(fun) :可以应用在并行流上以保持元素顺序
toArray()
toArray(T[] :: new): 返回正确的元素类型
collect(Collector):将搜集的元素返回,其中Collectors中有许多的搜集方法,自行了解
@Test
public void test4() {
List<Employee> employees = Arrays.asList(
new Employee(1, "张三", 15, 3325.665),
new Employee(2, "李四", 23, 3455.23),
new Employee(3, "王五", 43, 5562.025),
new Employee(4, "赵六", 12, 5623.665),
new Employee(5, "周期", 33, 4568.665),
new Employee(6, "王八", 21, 4459.665)
);
List<String> list = employees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.println("---------------------------");
HashSet<String> hashSet = employees.stream()
.map(Employee::getName)
.collect(Collectors.toCollection(HashSet::new));通过该方式放入指定的集和中。
hashSet.forEach(System.out::println);
}
输出的是Employee中的所有的名字
@Test
public void test5() {
List<Employee> employees = Arrays.asList(
new Employee(1, "张三", 15, 3325.665),
new Employee(2, "李四", 23, 3455.23),
new Employee(3, "王五", 43, 5562.025),
new Employee(4, "赵六", 12, 5623.665),
new Employee(5, "周期", 33, 4568.665),
new Employee(6, "王八", 21, 4459.665)
);
//员工的总数
Long collect = employees.stream()
.collect(Collectors.counting());
System.out.println(collect);//6
//工资平均值
Double collect2 = employees.stream()
.collect(Collectors.averagingDouble(Employee::getMoney));
System.out.println(collect2);
//工资的总数
Double collect3 = employees.stream()
.collect(Collectors.summingDouble(Employee::getMoney));
System.out.println(collect3);
//工资最大值
Optional<Employee> collect4 = employees.stream()
.collect(Collectors.maxBy((e1,e2)-> Double.compare(e1.getMoney(), e2.getMoney())));
System.out.println(collect4.get());
//工资的最小值
Optional<Double> collect5 = employees.stream()
.map(Employee::getMoney)
.collect(Collectors.minBy(Double::compare));
System.out.println(collect5.get());
}
Collect(Collectors) 的功能非常强大,Collectors 可以收集各种所要的数据集和,可以仿照数据库的各种查询操作,需要自行去了解其中的方法,在这不做过多的示例。
ForkJoin的基础运用
@Test
public void test1() {
Instant start = Instant.now();
long reduce = LongStream.range(0, 100000000L)
.parallel()
.reduce(0,Long::sum);
Instant end = Instant.now();//125310
System.out.println("耗费时间为:"+ Duration.between(start, end).toMillis());
}
Optional类,避免空指针异常
后序会深入学习