Stream API
2019独角兽企业重金招聘Python工程师标准>>>
Stream API**说明**
Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API。
Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
什么是 Stream
是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据**,Stream讲的是计算!”**
• ① Stream 不是集合,自己 不会存储元素。
• ② Stream 不会改变源对象。相反,他们会返回一个持有结果的新 Stream 。
• ③ Stream 操作 是延迟执行的 。必须搞清楚有哪些数据才能往下执行,这 意味着他们会等到需要结果的时候才执行 。
• ④ Stream 只能“消费”一次,如果想继续做其他操作,需要重新获取 stream 对象
④更像一个高级的iterator,单向,不可往复,数据只能遍历一次,遍历过一次后即用尽了,但是可以并行化数据!**哦也!!**\(^o^)/
并行**流与串行流**
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过 parallel() 与 sequential() 在并行流与顺序流之间进行切换。
Optional 类
到目前为止,臭名昭著的空指针异常是导致Java应用程序失败的最常见原因。以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写更干净的代码。受到Google Guava的启发,Optional类已经成为Java 8类库的一部分。
Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional
常用方法:
Optional.empty() : 创建一个空的 Optional 实例
Optional.of(T t) : 创建一个 Optional 实例
Optional.ofNullable**(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例**
isPresent() : 判断是否包含值
T get(): 如果调用对象包含值,返回该值,否则抛异常
orElse**(T t**) : 如果调用对象包含值,返回该值,否则返回**t**
orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值
map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()
flatMap(Function mapper):与 map 类似,要求返回值必须是Optional
package day26_1;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.junit.Test;
/**
* Stream是流, 是工作流
* 要处理批量的数据
*
* 1) Stream 不保存数据, 只处理数据
* 2) Stream 是延迟执行的, 只有最后的执行操作下达的时候才会执行其中的操作, 并且可以有多个流式处理
* 3) Stream 的消费是一次性的, 每处理一次都会产生一个新的流
* 4) Stream 不会修改数据源
*
* Stream操作有经典的3步
* 1) 创建流
* 2) 一系列的中间操作, 流水线, (可以省略)
* filter(Predicate p) // 流中的每个数据都要经过判定的判定, 如果判断结果为真的留下, 假的丢弃。
* distinct(); 去重依据的是对象的hashCode和equals
* limit(int size) 限制最多的个数
* sorted() 自然排序
* sorted(Comparator com) 定制排序
* map(Function fun) 把流中的所有数据转换为另外的类型并产生新流
*
* 3) 终止流
* Optional<T> findFirst(); // 返回流中的第一个元素
* long count();
* reduce(BinaryOperator bo) ;// 二元运算, 两输入一输出, 最后产生一个结果
* collect()收集
*
* Optional 的正确用法 , 尽量避免空指针
* orElse(非空);
*/
public class SteamTest {
@Test
public void test13() {
Stream<Student> stream = StudentData.getList().stream();
//stream.parallel();
Set<Student> set = stream.distinct().collect(Collectors.toSet()); // toList
for (Student student : set) {
System.out.println(student);
}
}
@Test
public void test12() {
Stream<Student> stream = StudentData.getList().stream();
// 找出最高分
Optional<Double> optional = stream.distinct().map(t -> t.getScore()).reduce((t1, t2) -> t1 > t2 ? t1 : t2);
System.out.println(optional.orElse(101.0));
}
@Test
public void test11() {
Stream<Student> stream = StudentData.getList().stream();
// 统计有几个五年级同学
long count = stream.distinct().filter(t -> t.getGrade() == 5).count();
System.out.println(count);
}
@Test
public void test10() {
Stream<Student> stream = StudentData.getList().stream();
Optional<Student> findFirst = stream.distinct().filter(t -> t.getGrade() == 3).findFirst();
//System.out.println(findFirst.get());
System.out.println(findFirst.orElse(new Student()).toString());
}
@Test
public void test9() {
Stream<Student> stream = StudentData.getList().stream();
stream.distinct().map(t -> t.getScore()).forEach(System.out::println);
}
@Test
public void test8() {
Stream<Student> stream = StudentData.getList().stream();
stream.sorted((t1, t2) -> t1.getGrade() - t2.getGrade()).forEach(System.out::println);
}
@Test
public void exer2() {
//找出3年级中没有及格的同学, 倒序排序, 并取出前2个3年级同学.
Stream<Student> stream = StudentData.getList().stream();
stream.distinct().filter(t->t.getGrade()==3).filter(t->t.getScore()<60)
.sorted((t1, t2) -> (int)(t2.getScore() - t1.getScore())).limit(2).forEach(System.out::println);
}
@Test
public void test7() {
Stream<Student> stream = StudentData.getList().stream();
stream.distinct().limit(50).forEach(System.out::println);
}
@Test
public void test6() {
Stream<Student> stream = StudentData.getList().stream();
stream.distinct().forEach(System.out::println);
}
@Test
public void test5() {
Stream<Student> stream = StudentData.getList().stream();
// 所有姓张的并且及格的
stream.filter(t -> t.getScore() >= 60).filter(t -> t.getName().startsWith("张")).forEach(System.out::println);
}
@Test
public void exer1() {
// 找出3年级没有及格的同学
Stream<Student> stream = StudentData.getList().stream();
stream.filter(t -> t.getGrade() == 3).filter(t -> t.getScore() < 60).forEach(System.out::println);
}
@Test
public void test4() {
// 无限流
//Stream<Integer> generate = Stream.generate(() -> 100);
Stream<Double> generate = Stream.generate(Math::random);
generate.forEach(System.out::println);
}
@Test
public void test3() {
// 基于一些散数据
Stream<String> stream = Stream.of("abc", "xxx", "zzz", "yyy", "qq");
stream.forEach(System.out::println);
}
@Test
public void test2() {
// 基于数组
Integer[] arr = {1, 3, 8, 9, 10};
Stream<Integer> stream = Arrays.stream(arr);
//stream.forEach(t -> System.out.println(t));
stream.forEach(System.out::println); // 方法引用的方式
}
@Test
public void test1() {
// 基于集合获取流
List<Student> list = StudentData.getList();
Stream<Student> stream = list.stream();
// 终止流 , forEach(Consumer con); // 把流中的每个对象都经过这个消费器消费一下
stream.forEach(t -> System.out.println(t));
//stream.forEach(t -> System.out.println(t)); 必须一次性使用流
}
}
转载于//my.oschina.net/architectliuyuanyuan/blog/3048182
还没有评论,来说两句吧...