您的位置:首页 > 编程语言 > Java开发

Java8最具革命性新特性之StreamAPI

2019-07-30 09:26 190 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/LINHONG_1994/article/details/97751528

上一篇总结了Lambda表达式,本篇主要对StreamAPI进行总结归纳,这是Java8中两大最为重要的改变。StreamAPI(java.util.stream)是真正的函数式编程风格引入到Java中。是目前为止对Java类库最好的补充,因为Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

1.Stream是什么,有什么特点?

  Stream是什么数据处理流,是对内存中的数据,一般是集合或数组中的数据进行处理用的。Stream只负责对数据进行处理(筛选、过滤、统计、遍历显示等),不负责存储。存储数据仍然由集合、数组等容器完成Stream对数据的处理是不修改集合和数组,只会返回处理后的结果。类似select的sql查询语句对数据库进行查询,得到结果,但是查询不会修改数据库中的数据。

Stream特点:

  ①Stream对数据的处理是不修改集合和数组,只会返回处理后的结果

  ②Stream操作是一个延迟操作,如果没有进行终结操作之前,之前的操作是不会执行的

  ③Stream是不可变对象 即,每次调用stream的中间操作方法后,必须重新用Stream的对象接收,否则就会有问题,或者进行连写操作。

2.Stream数据流创建方式(4种)

  ①通过集合创建 -----> 集合对象.stream()

  ②通过数组工具类 -----> Arrays.stream(数组对象)

  ③Stream.of

  ④无限流 -----> Stream.generate(Supplier s)

代码示例01:
public class TestStream01 {
@Test
public void test01(){
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}

//Java8给集合添加了stream()
Stream<Integer> stream = list.stream();// (1)集合对象.stream()
}

@Test
public void test02(){
int[] arr = {1,2,3,4,5};
IntStream stream = Arrays.stream(arr);//(2)Arrays.stream(数组对象)
}

@Test
public void test03(){
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);//(3)Stream.of
}

@Test
public void test04(){
Stream<Double> stream = Stream.generate(Math::random);//
3ff7
(5)Stream.generate(Supplier<T> s)
}

}
3.Stream的操作步骤(3步)

  ①创建Stream

  ②中间操作 (0~n步的筛选、排序…)

  ③终结操作

代码示例02:
public class TestStream02 {
@Test
public void test05(){
//创建流
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
//中间操作
//Consumer  void accept(T t)
stream = stream.peek(System.out::println);

//终结操作
long count = stream.count();
System.out.println("个数:"+count);
}

@Test
public void test06(){
//创建流
Stream<Double> stream = Stream.generate(Math::random);

//终结操作
stream.forEach(System.out::println);
}

@Test
public void test07(){
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}

//Java8给集合添加了stream()
Stream<Integer> stream = list.stream();
//过滤:filter
//Predicate<T> boolean test(T t)
stream = stream.filter(num -> num%3==0);

stream.forEach(System.out::println);
System.out.println(list);
}

@Test
public void test08(){
//创建流、中间、终结    进行了“连写”
Stream.generate(Math::random)
.limit(10)
.filter(num->num>0.5)
.distinct()
.forEach(System.out::println);
}
}
4.Stream的操作步骤之中间操作

  中间操作常见方法:0~n步

  ①filter(Predicate p):过滤

  ②distinct():去重

  ③limit(long maxSize):限制几个

  ④skip(long n):跳过几个

  ⑤sorted():排序 (用元素的自然排序)

  sorted(Comparator com):排序 (用定制排序)

  ⑥peek(Consumer action):对流中的数据进行Consumer指定的操作,但是不影响元素的个数

  ⑦map(Function f):映射

  ⑧mapToDouble(ToDoubleFunction f)

  ⑨flatMap(Function f) :扁平映射

代码示例03:
public class TestMiddle {

@Test
public void test13(){
//把流中的"hello:java"等,拆开,合并成一个新的流
Stream.of("hello:java","atguigu:good","world:big")
/*
* <R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
* Function<T,R>    R apply(T t)
* Function<T,R>    Stream<R> apply(T t)
* Function<String,R>    Stream<R> apply(String t)
*
* t.split(":")返回值类型    String[]
*/
.flatMap(t -> Stream.of(t.split(":")))
.forEach(System.out::println);

}

@Test
public void test12(){
ArrayList<Employee> list = new ArrayList<>();
list.add(new Employee("张三", 13000));
list.add(new Employee("李四", 14000));
list.add(new Employee("王五", 9000));

//用流操作集合的元素
//(1)打印流中的每一个元素
//(2)只保留薪资是10000以上的
//(3)统计最后留下的员工的薪资总数
OptionalDouble sum = list.stream()
.peek(System.out::println)
.filter(e -> e.getSalary()>10000)
/*
* ToDoubleFunction   抽象方法   double applyAsDouble(T value)
*/
.mapToDouble(e -> e.getSalary())
/*
* DoubleBinaryOperator   抽象方法 double applyAsDouble(double left, double right)
*/
.reduce((a,b)->a+b);
System.out.println("sum = " + sum);

}

@Test
public void test11(){
//假设,把流中的字符串的首字母变为大写
Stream.of("hello","java","world")
/*
* Function<T,R>  R apply(T t)
*/
.map(str -> Character.toUpperCase(str.charAt(0)) + str.substring(1))
.forEach(System.out::println);
}

@Test
public void test10(){
//假设,把流中的数据都扩大2倍
Stream.of(1,2,3,4,5)
/*
* Function<T,R>  R apply(T t)
*/
.map(num -> num*2)
.forEach(System.out::println);
}

@Test
public void test09(){
//对流中的数据进行去重、打印、统计最后的元素个数
long c = Stream.of(11,20,1,3,4,44,23,11,20,34,2,2,5,6)
.distinct()//中间操作1
.peek(t -> System.out.println(t))//中间操作1
.count();//终结
System.out.println("数量是:"+c);
}

@Test
public void test08(){
//对流中的数据进行排序,取出第三大的
Stream.of(11,20,1,3,4,44,23,11,20,34,2,2,5,6)
.sorted((n1,n2)-> -Integer.compare(n1, n2))
.distinct()
.limit(3)
.skip(2)
.forEach(str -> System.out.println(str));
}

@Test
public void test07(){
//对流中的数据进行排序,取出最大的三个
Stream.of(11,20,1,3,4,44,23,11,20,34,2,2,5,6)
.sorted((n1,n2)-> -Integer.compare(n1, n2))
.distinct()
.limit(3)
.forEach(str -> System.out.println(str));
}

@Test
public void test06(){
//对流中的数据进行排序,取出最小的三个
Stream.of(11,20,1,3,4,44,23,11,20,34,2,2,5,6)
.sorted()
.distinct()
.limit(3)
.forEach(str -> System.out.println(str));
}

@Test
public void test05(){
Stream.of(1,2,1,3,4,2,5,6)
.distinct()   //1,2,3,4,5,6
.skip(3)		//4,5,6
.forEach(str -> System.out.println(str));
}

@Test
public void test04(){
Stream.generate(Math::random)
.limit(5)
.forEach(num -> System.out.println(num));
}

@Test
public void test03(){
Stream.of(1,2,1,3,4,2,5,6)
.distinct()
.filter(num -> num<5)
.forEach(str -> System.out.println(str));
}

@Test
public void test02(){
Stream.of(1,2,1,3,4,2,5,6)
.distinct()
.forEach(str -> System.out.println(str));
}

@Test
public void test01(){
Stream.of("hello","world","java","hi","atguigu")
/*
* Predicate<T>:判断型接口   boolean test(T t)
*/
.filter(str -> str.length()<=5)
/*
* Consumer<T> void accept(T t)
*/
.forEach(str -> System.out.println(str));

}
}
class Employee{
private String name;
private double salary;
public Employee(String name, double salary) {
super();
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Employee [name=" + name + ", salary=" + salary + "]";
}

}
5.Stream的操作步骤之终结操作

终结操作常见方法:

  ①void forEach(Consumer c):遍历流中的元素

  ②long count():统计流中的元素的总个数

  ③U reduce(BinaryOperator b) :对流中的元素,反复执行某个操作,得到最后的一个总结果

  ④boolean allMatch(Predicate p):是否都匹配

  ⑤boolean noneMatch(Predicate p):是否都不匹配

  ⑥boolean anyMatch(Predicate p):任意一个匹配

  ⑦Optional findFirst():查找第一个

  ⑧Optional max(Comparator c) :比较最大值

  ⑨Optional min(Comparator c):比较小大值

  ⑩R collect(Collector c):收集(把处理完的结果收集到集合等里面)

代码示例04:
public class TestEnding {
@Test
public void test05(){
List<Integer> list = Stream.of(1,2,3,4,5,6,7,8)
.filter(num -> num%2==0)<
8000
/span>
/*
* java.util.stream.Collector接口
* 它有一个工具类  java.util.stream.Collectors工具类
*/
.collect(Collectors.toList());
System.out.println(list);
}

@Test
public void test04(){
Optional<Integer> first = Stream.of(1,2,3,4)
.sorted((t1,t2) -> Integer.compare(t2, t1))
.findFirst();
System.out.println(first);
}

@Test
public void test03(){
//是否都是奇数
boolean allMatch = Stream.of(1,21,3,5,7)
/*
* Predicate<T>  boolean test(T t)
*/
.allMatch(num -> num%2!=0);
System.out.println(allMatch);
}

@Test
public void test02(){
Optional<Integer> max = Stream.of(1,2,3,4,5)
/*
* BinaryOperator  T apply(T t1, T t2)
*/
.reduce((t1,t2) -> t1>t2?t1:t2);
System.out.println(max);
}

@Test
public void test01(){
Optional<Integer> sum = Stream.of(1,2,3,4)
/*
* BinaryOperator  T apply(T t1, T t2)
*/
.reduce((t1,t2) -> t1+t2);
System.out.println(sum);
}
}

推荐阅读往期博文:

【JavaSE】Java8最具革命性新特性之Lambda表达式

#轻松一刻

☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!

☞本人博客:https://coding0110lin.blog.csdn.net/  欢迎转载,一起技术交流吧!

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: