StreamAPI的说明

Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另外一个则是 Stream API。

Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

为什么要用StreamAPI

实际开发中,项目中多数数据源都来自于Mysql,Oracle等。但现在数据源可以更多了,有MongDB,Radis等,而这些NoSQL的数据就需要java层面去处理。

Stream到底是是什么

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,Stream讲的是计算!”



注意:

Stream 自己不会存储元素。

Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。

Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

Stream操作的三个步骤

1- 创建 Stream

一个数据源(如:集合、数组),获取一个流

2- 中间操作

一个中间操作链,对数据源的数据进行处理

3- 终止操作(终端操作)

一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用

如图所示:

创建Stream

有三种方式:

1、通过集合(Java8中的Collection接口被扩展没提供了两个获取流的方法 Stream() parallelStream())

2、通过数组(Java8 中的 Arrays 的静态方法 stream() 可以获取数组流 static Stream stream(T[] array): 返回一个流)

3、通过Stream的of()方法(可以调用Stream类静态方法 of(), 通过显示值创建一个流。它可以接收任意数量的参数 public static Stream of(T... values) : 返回一个流)

首先有个Person类

  1. package com.xnn.lambda;
  2. /**
  3. * 类(接口)描述:
  4. * @author xnn
  5. * 2018年10月21日下午3:05:37
  6. */
  7. public class Person {
  8. private String name;
  9. private int age;
  10. private double salary;
  11. private Status status;
  12. /**
  13. * @return the name
  14. */
  15. public String getName() {
  16. return name;
  17. }
  18. /**
  19. * @param name the name to set
  20. */
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. /**
  25. * @return the age
  26. */
  27. public int getAge() {
  28. return age;
  29. }
  30. /**
  31. * @param age the age to set
  32. */
  33. public void setAge(int age) {
  34. this.age = age;
  35. }
  36. /**
  37. * @return the salary
  38. */
  39. public double getSalary() {
  40. return salary;
  41. }
  42. public void setSalary(double salary) {
  43. this.salary = salary;
  44. }
  45. /**
  46. * @param name
  47. * @param age
  48. * @param salary
  49. * @param status
  50. */
  51. public Person(String name, int age, double salary, Status status) {
  52. super();
  53. this.name = name;
  54. this.age = age;
  55. this.salary = salary;
  56. this.status = status;
  57. }
  58. public Person() {
  59. super();
  60. }
  61. /**
  62. * @return the status
  63. */
  64. public Status getStatus() {
  65. return status;
  66. }
  67. /**
  68. * @param status the status to set
  69. */
  70. public void setStatus(Status status) {
  71. this.status = status;
  72. }
  73. /**
  74. * @param name
  75. * @param age
  76. * @param salary
  77. */
  78. public Person(String name, int age, double salary) {
  79. super();
  80. this.name = name;
  81. this.age = age;
  82. this.salary = salary;
  83. }
  84. /* (non-Javadoc)
  85. * @see java.lang.Object#hashCode()
  86. */
  87. @Override
  88. public int hashCode() {
  89. final int prime = 31;
  90. int result = 1;
  91. result = prime * result + age;
  92. result = prime * result + ((name == null) ? 0 : name.hashCode());
  93. long temp;
  94. temp = Double.doubleToLongBits(salary);
  95. result = prime * result + (int) (temp ^ (temp >>> 32));
  96. result = prime * result + ((status == null) ? 0 : status.hashCode());
  97. return result;
  98. }
  99. /* (non-Javadoc)
  100. * @see java.lang.Object#equals(java.lang.Object)
  101. */
  102. @Override
  103. public boolean equals(Object obj) {
  104. if (this == obj)
  105. return true;
  106. if (obj == null)
  107. return false;
  108. if (getClass() != obj.getClass())
  109. return false;
  110. Person other = (Person) obj;
  111. if (age != other.age)
  112. return false;
  113. if (name == null) {
  114. if (other.name != null)
  115. return false;
  116. } else if (!name.equals(other.name))
  117. return false;
  118. if (Double.doubleToLongBits(salary) != Double
  119. .doubleToLongBits(other.salary))
  120. return false;
  121. if (status != other.status)
  122. return false;
  123. return true;
  124. }
  125. /* (non-Javadoc)
  126. * @see java.lang.Object#toString()
  127. */
  128. @Override
  129. public String toString() {
  130. return "Person [name=" + name + ", age=" + age + ", salary=" + salary
  131. + ", status=" + status + "]";
  132. }
  133. public enum Status {
  134. FREE,
  135. BUSY,
  136. VACATION;
  137. }
  138. }

  1. package com.xnn.stream;
  2. import java.util.Arrays;
  3. import java.util.List;
  4. import java.util.Optional;
  5. import java.util.stream.Stream;
  6. import org.junit.Test;
  7. import com.xnn.lambda.Person;
  8. /**
  9. * 类(接口)描述:Stream 操作的三个步骤
  10. * 1.创建流
  11. * 2.做一些中间操作
  12. * 3.做终止操作
  13. * @author xnn
  14. * 2018年10月22日下午2:56:26
  15. */
  16. public class TestStreamAPI {
  17. //获取流的第一种方式 (Java8中的Collection接口被扩展没提供了两个获取流的方法 Stream() parallelStream())
  18. List<Person> person = Arrays.asList(
  19. new Person("李四", 59, 6666.66),
  20. new Person( "张三", 18, 9999.99),
  21. new Person( "王五", 28, 3333.33),
  22. new Person( "赵六", 8, 7777.77),
  23. new Person( "田七", 38, 5555.55)
  24. );
  25. @Test
  26. public void test1() {
  27. //获取一个顺序流
  28. Stream<Person> stream = person.stream();
  29. System.out.println(stream);
  30. //获取一个并行流
  31. Stream<Person> parallelStream = person.parallelStream();
  32. System.out.println(parallelStream);
  33. //获取流的第二种方式 ——由数组创建流
  34. Integer arr[] = new Integer[] {1,4,5,6,78,7};
  35. Stream<Integer> stream2 = Arrays.stream(arr);
  36. Optional<Integer> first = stream2.findFirst();
  37. System.out.println(first);
  38. //获取流的第三种方式——可以使用静态方法 Stream.of(),即用值创建流
  39. Stream<String> stream3 = Stream.of("y7yiu");
  40. }
  41. @Test
  42. public void test2() {
  43. //创建无限流
  44. //迭代的方式创建无限流
  45. Stream.iterate(0,(x)->x+2).limit(10)
  46. .forEach(System.out::println);;
  47. //生成的方式产生无限流
  48. Stream.generate(()->Math.random()).limit(3).forEach(System.out::println);;
  49. }
  50. }

运行结果:

  1. java.util.stream.ReferencePipeline$Head@5ef04b5
  2. java.util.stream.ReferencePipeline$Head@5f4da5c3
  3. Optional[1]
  4. 0
  5. 2
  6. 4
  7. 6
  8. 8
  9. 10
  10. 12
  11. 14
  12. 16
  13. 18
  14. 0.20849306218015928
  15. 0.526378190370348
  16. 0.6520277965773994

Stream的中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。

中间操作——筛选与切片



代码示例

  1. *
  2. */
  3. package com.xnn.stream;
  4. import java.net.StandardSocketOptions;
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. import java.util.Collections;
  8. import java.util.HashSet;
  9. import java.util.List;
  10. import java.util.Map;
  11. import java.util.Map.Entry;
  12. import java.util.Optional;
  13. import java.util.Set;
  14. import java.util.function.Function;
  15. import java.util.function.Predicate;
  16. import java.util.stream.Collector;
  17. import java.util.stream.Collectors;
  18. import java.util.stream.Stream;
  19. import org.junit.Test;
  20. import com.xnn.lambda.Person;
  21. import com.xnn.lambda.Person.Status;
  22. /**
  23. * 类(接口)描述://中间操作
  24. *
  25. * @author xnn 2018年10月22日下午3:27:12
  26. */
  27. public class TestStreamAPI2 {
  28. List<Person> person = Arrays.asList(
  29. new Person("李四", 59, 6666.66, Status.FREE),
  30. new Person("张三", 18, 9999.99, Status.FREE),
  31. new Person("王五", 28, 3333.33, Status.BUSY),
  32. new Person("赵六", 8, 7777.77, Status.VACATION),
  33. new Person("田七", 38, 5555.55, Status.BUSY),
  34. new Person("田七", 38, 5555.55, Status.VACATION),
  35. new Person("田七", 38, 5555.55, Status.VACATION)
  36. );
  37. /*
  38. * 筛选与切片 filter——接收 Lambda , 从流中排除某些元素。 limit——截断流,使其元素不超过给定数量。
  39. * skip(n) ——跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。
  40. * 与 limit(n) 互补
  41. * distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
  42. */
  43. @Test
  44. public void test1() {
  45. // 先获取流
  46. Stream<Person> stream = person.stream();
  47. // 筛选 Stream<T> filter(Predicate<? super T> predicate);
  48. // Predicate接口的test方法 传递进去一个T 返回一个Boolean
  49. // filter——接收 Lambda , 从流中排除某些元素
  50. // 这个forEach被称为是内部迭代
  51. stream.filter((u) -> {
  52. System.out.println("中间操作");
  53. //筛选出年龄大于20 的人员
  54. return u.getAge() > 20;
  55. }).forEach(System.out::println);
  56. System.out.println("==============================");
  57. /**
  58. * 下面这一部分由于没有终止操作,所以"中间操作"这四个字并没有打印出来,只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”
  59. */
  60. Stream<Person> stream4 = person.stream();
  61. stream4.filter((u) -> {
  62. System.out.println("中间操作");
  63. return u.getAge() > 20;
  64. });
  65. System.out.println("==============================");
  66. // 必须再创建一个新流 目测是新功能的时候,不能用上面的流,否则会报流已经打开或关闭的错误
  67. Stream<Person> stream1 = person.stream();
  68. // limit——截断流,使其元素不超过给定数量
  69. //筛选出年龄大于20岁的人元信息后,只取前两个值
  70. stream1.filter((u) -> u.getAge() > 20).limit(2)
  71. .forEach(System.out::println);
  72. System.out.println("==============================");
  73. // skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
  74. Stream<Person> stream2 = person.stream();
  75. //筛选出年龄大于20岁的人元信息后,跳过第一个人,取后面的值
  76. stream2.filter((u) -> u.getAge() > 20).skip(1)
  77. .forEach(System.out::println);
  78. System.out.println("==============================");
  79. // distinct——筛选,通过流所生成元素的 hashCode() 和 equals()这样去除重复元素(意即需要重写实体类的hashcode 和equals方法)
  80. Stream<Person> stream3 = person.stream();
  81. stream3.filter((u) -> u.getAge() > 20).distinct()
  82. .forEach(System.out::println);
  83. }
  84. }

运行结果:

中间操作——映射



代码示例

  1. package com.xnn.stream;
  2. import java.net.StandardSocketOptions;
  3. import java.util.ArrayList;
  4. import java.util.Arrays;
  5. import java.util.Collections;
  6. import java.util.HashSet;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Map.Entry;
  10. import java.util.Optional;
  11. import java.util.Set;
  12. import java.util.function.Function;
  13. import java.util.function.Predicate;
  14. import java.util.stream.Collector;
  15. import java.util.stream.Collectors;
  16. import java.util.stream.Stream;
  17. import org.junit.Test;
  18. import com.xnn.lambda.Person;
  19. import com.xnn.lambda.Person.Status;
  20. /**
  21. * 类(接口)描述://中间操作
  22. *
  23. * @author xnn 2018年10月22日下午3:27:12
  24. */
  25. public class TestStreamAPI2 {
  26. List<Person> person = Arrays.asList(
  27. new Person("李四", 59, 6666.66, Status.FREE),
  28. new Person("张三", 18, 9999.99, Status.FREE),
  29. new Person("王五", 28, 3333.33, Status.BUSY),
  30. new Person("赵六", 8, 7777.77, Status.VACATION),
  31. new Person("田七", 38, 5555.55, Status.BUSY),
  32. new Person("田七", 38, 5555.55, Status.VACATION),
  33. new Person("田七", 38, 5555.55, Status.VACATION)
  34. );
  35. /**
  36. * 映射: 1、map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  37. * 2、mapToDouble(ToDoubleFunction f)) 接收一个函数作为参数,该函数会被应用到每个素上,产生一个新的
  38. * DoubleStream 3、mapToInt(ToIntFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的
  39. * IntStream。 4、mapToLong(ToLongFunction f) 接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的
  40. * LongStream 5、flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
  41. *
  42. * @author:xnn 2018年10月22日下午3:55:54
  43. */
  44. @Test
  45. public void test2() {
  46. Stream<Person> stream = person.stream();
  47. // 1、map(Function f) 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  48. // 把姓名的集合取出来
  49. // stream.map((x)->x.getName()).forEach(System.out::println);
  50. //方法引用的方式写的
  51. stream.map(Person::getName).forEach(System.out::println);
  52. System.out.println("================");
  53. // 2、mapToDouble(ToDoubleFunction f)) 接收一个函数作为参数,该函数会被应用到每个素上,产生一个DoubleStream
  54. Stream<Person> stream1 = person.stream();
  55. // stream1.mapToDouble((x)->x.getSalary())
  56. // .forEach(System.out::println);
  57. // 另一种写法 即:接受了Person类的getSalary()方法为参数,把薪资全都取出胡来了
  58. stream1.mapToDouble(Person::getSalary).forEach(System.out::println);
  59. System.out.println("================");
  60. // 3、mapToInt(ToIntFunction f)接收一个函数作为参数,该函数会被应用到每个元素上,产生一个新的 IntStream。
  61. Stream<Person> stream2 = person.stream();
  62. stream2.mapToInt(Person::getAge).forEach(System.out::println);
  63. System.out.println("================");
  64. Stream<String> stream3 = Stream.of("aaa", "bbb", "ccc", "ddd");
  65. Stream<Stream<Character>> map =
  66. /*TestStreamAPI2::filterCharacter就代表把每一个字符串("aaa","bbb"...)都进行filterCharacter()处理,
  67. 这时候每个字母,都变成了一个流,而map()方法返回的也是一个流,所以返回值就成了Stream<Stream<Character>>*/
  68. stream3.map(TestStreamAPI2::filterCharacter);
  69. //用map的话还得多重遍历(sm 代表一个Stream<Character>,所以再对sm进行了遍历)
  70. map.forEach((sm)->sm.forEach(System.out::println));
  71. System.out.println("++++++++++++++++++++++++++");
  72. // flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,
  73. //然后把所有流连接成一个流(是个关键)
  74. Stream<String> stream4 = Stream.of("aaa", "bbb", "ccc", "ddd");
  75. Stream<Character> flatMap = stream4
  76. .flatMap(TestStreamAPI2::filterCharacter);
  77. flatMap.forEach(System.out::println);
  78. System.out.println("==============");
  79. /**
  80. * map 和flatmap类似于list集合的add()方法和addAll()方法
  81. */
  82. List<Object> list =new ArrayList<>();
  83. List<Object> list2 =new ArrayList<>();
  84. list.add("aaa");
  85. list.add("bbb");
  86. list2.add("1");
  87. //add是把集合加进去了
  88. list2.add(list);
  89. System.out.println(list2);
  90. System.out.println("+++++++++++++++++++++++++");
  91. List<Object> list3 =new ArrayList<>();
  92. List<Object> list4 =new ArrayList<>();
  93. list3.add("aaa");
  94. list3.add("bbb");
  95. list4.add("1");
  96. //addAll是把集合中的每一个元素加进去了
  97. list4.addAll(list3);
  98. System.out.println(list4);
  99. }
  100. // 把字符串转化为字符数组流
  101. public static Stream<Character> filterCharacter(String str) {
  102. List<Character> list = new ArrayList<>();
  103. for (Character character : str.toCharArray()) {
  104. list.add(character);
  105. }
  106. return list.stream();
  107. }
  108. }

运行结果

  1. 李四
  2. 张三
  3. 王五
  4. 赵六
  5. 田七
  6. 田七
  7. 田七
  8. ================
  9. 6666.66
  10. 9999.99
  11. 3333.33
  12. 7777.77
  13. 5555.55
  14. 5555.55
  15. 5555.55
  16. ================
  17. 59
  18. 18
  19. 28
  20. 8
  21. 38
  22. 38
  23. 38
  24. ================
  25. a
  26. a
  27. a
  28. b
  29. b
  30. b
  31. c
  32. c
  33. c
  34. d
  35. d
  36. d
  37. ++++++++++++++++++++++++++
  38. a
  39. a
  40. a
  41. b
  42. b
  43. b
  44. c
  45. c
  46. c
  47. d
  48. d
  49. d
  50. ==============
  51. add的结果:[1, [aaa, bbb]]
  52. +++++++++++++++++++++++++
  53. addAll的结果:[1, aaa, bbb]

中间操作——排序



代码示例

  1. package com.xnn.stream;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Optional;
  8. import java.util.stream.Collectors;
  9. import java.util.stream.Stream;
  10. import org.junit.Test;
  11. import com.xnn.lambda.Person;
  12. import com.xnn.lambda.Person.Status;
  13. /**
  14. * 类(接口)描述://中间操作
  15. *
  16. * @author xnn 2018年10月22日下午3:27:12
  17. */
  18. public class TestStreamAPI2 {
  19. List<Person> person = Arrays.asList(
  20. new Person("李四", 59, 6666.66, Status.FREE),
  21. new Person("张三", 18, 9999.99, Status.FREE),
  22. new Person("王五", 28, 3333.33, Status.BUSY),
  23. new Person("赵六", 8, 7777.77, Status.VACATION),
  24. new Person("田七", 38, 5555.55, Status.BUSY),
  25. new Person("田七", 38, 5555.55, Status.VACATION),
  26. new Person("田七", 38, 5555.55, Status.VACATION)
  27. );
  28. /**
  29. * sorted() 产生一个新流,其中按自然顺序 sorted(Comparator comp) 产生一个新流,其中按比较器顺序
  30. */
  31. @Test
  32. public void test3() {
  33. // sorted() 产生一个新流,其中按自然顺序
  34. List<String> list = Arrays.asList("aa", "bb", "cc", "dd", "ee");
  35. Stream<String> stream = list.stream();
  36. stream.sorted().forEach(System.out::println);
  37. System.out.println("-------------------------");
  38. // sorted(Comparator comp) 产生一个新流,其中按比较器顺序
  39. person.stream().sorted((e1, e2) -> {
  40. /**
  41. * 年龄相同按姓名排序,否则按年龄排序
  42. */
  43. if (e1.getAge() == e2.getAge()) {
  44. return e1.getName().compareTo(e2.getName());
  45. } else {
  46. return Integer.compare(e1.getAge(), e2.getAge());
  47. }
  48. }).forEach(System.out::println);;
  49. }
  50. }

运行结果

  1. aa
  2. bb
  3. cc
  4. dd
  5. ee
  6. -------------------------
  7. Person [name=赵六, age=8, salary=7777.77, status=VACATION]
  8. Person [name=张三, age=18, salary=9999.99, status=FREE]
  9. Person [name=王五, age=28, salary=3333.33, status=BUSY]
  10. Person [name=田七, age=38, salary=5555.55, status=BUSY]
  11. Person [name=田七, age=38, salary=5555.55, status=VACATION]
  12. Person [name=田七, age=38, salary=5555.55, status=VACATION]
  13. Person [name=李四, age=59, salary=6666.66, status=FREE]

Stream 的终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void 。

流进行了终止操作后,不能再次使用。

终止操作——匹配与查找



代码示例

  1. package com.xnn.stream;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Optional;
  8. import java.util.stream.Collectors;
  9. import java.util.stream.Stream;
  10. import org.junit.Test;
  11. import com.xnn.lambda.Person;
  12. import com.xnn.lambda.Person.Status;
  13. /**
  14. * 类(接口)描述://中间操作
  15. *
  16. * @author xnn 2018年10月22日下午3:27:12
  17. */
  18. public class TestStreamAPI2 {
  19. List<Person> person = Arrays.asList(
  20. new Person("李四", 59, 6666.66, Status.FREE),
  21. new Person("张三", 18, 9999.99, Status.FREE),
  22. new Person("王五", 28, 3333.33, Status.BUSY),
  23. new Person("赵六", 8, 7777.77, Status.VACATION),
  24. new Person("田七", 38, 5555.55, Status.BUSY),
  25. new Person("田七", 38, 5555.55, Status.VACATION),
  26. new Person("田七", 38, 5555.55, Status.VACATION)
  27. );
  28. /**
  29. * stream的终止操作(查找与匹配)
  30. * 1、allMatch(Predicate p) 检查是否匹配所有元素
  31. * 2、anyMatch(Predicate p) 检查是否至少匹配一个元素
  32. * 3、noneMatch(Predicate p)检查是否没有匹配所有元素
  33. * 4、findFirst() 返回第一个元素
  34. * 5、findAny() 返回当前流中的任意元素
  35. * @author:xnn 2018年10月23日下午2:48:07
  36. */
  37. @Test
  38. public void test4() {
  39. // allMatch(Predicate p) 检查是否匹配所有元素,即所有元素的status是BUSY才返回true
  40. boolean b = person.stream()
  41. .allMatch((e) -> e.getStatus().equals(Status.BUSY));
  42. System.out.println(b);
  43. System.out.println("===================");
  44. // anyMatch(Predicate p) 检查是否至少匹配一个元素,只要有一个元素的status是BUSY就返回true
  45. boolean c = person.stream()
  46. .anyMatch((w) -> w.getStatus().equals(Status.BUSY));
  47. System.out.println(c);
  48. System.out.println("===================");
  49. // noneMatch(Predicate p) 检查是否没有匹配所有元素,即 所有的元素的status都不是BUSY才返回true
  50. boolean d = person.stream()
  51. .noneMatch((q) -> q.getStatus().equals(Status.BUSY));
  52. System.out.println(d);
  53. System.out.println("===================");
  54. // findFirst() 返回第一个元素,返回符合条件的第一个元素
  55. Optional<Person> findFirst = person.stream().sorted(
  56. (e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
  57. .findFirst();
  58. System.out.println(findFirst.get());
  59. System.out.println("========================");
  60. // findAny() 返回当前流中的任意元素()
  61. Optional<Person> any = person.parallelStream()
  62. .filter((e) -> e.getStatus().equals(Status.BUSY)).findAny();
  63. System.out.println(any);
  64. }
  65. }

运行结果

  1. false
  2. ===================
  3. true
  4. ===================
  5. false
  6. ===================
  7. Person [name=王五, age=28, salary=3333.33, status=BUSY]
  8. ========================
  9. Optional[Person [name=田七, age=38, salary=5555.55, status=BUSY]]

终止操作——匹配与查找二



代码示例:


  1. package com.xnn.stream;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Optional;
  8. import java.util.stream.Collectors;
  9. import java.util.stream.Stream;
  10. import org.junit.Test;
  11. import com.xnn.lambda.Person;
  12. import com.xnn.lambda.Person.Status;
  13. /**
  14. * 类(接口)描述://中间操作
  15. *
  16. * @author xnn 2018年10月22日下午3:27:12
  17. */
  18. public class TestStreamAPI2 {
  19. List<Person> person = Arrays.asList(
  20. new Person("李四", 59, 6666.66, Status.FREE),
  21. new Person("张三", 18, 9999.99, Status.FREE),
  22. new Person("王五", 28, 3333.33, Status.BUSY),
  23. new Person("赵六", 8, 7777.77, Status.VACATION),
  24. new Person("田七", 38, 5555.55, Status.BUSY),
  25. new Person("田七", 38, 5555.55, Status.VACATION),
  26. new Person("田七", 38, 5555.55, Status.VACATION)
  27. );
  28. /**
  29. * 1、count() 返回流中元素总数
  30. * 2、max(Comparator c) 返回流中最大值
  31. * 3、min(Comparator c)返回流中最小值
  32. * 4、forEach(Consumer c) 内部迭代(使用 Collection接口需要用户去做迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代做
  33. */
  34. @Test
  35. public void test5() {
  36. // count() 返回流中元素总数
  37. long count = person.stream().count();
  38. System.out.println(count);
  39. System.out.println("=======华丽的分割线========");
  40. // max(Comparator c) 返回流中最大值
  41. Optional<Person> max = person.stream().max(
  42. (e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
  43. System.out.println("最高工资员工为" + max);
  44. System.out.println("=======华丽的分割线========");
  45. // min(Comparator c) 返回流中最小值
  46. Optional<Person> min = person.stream().min(
  47. (e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
  48. System.out.println("最低工资员工为" + min);
  49. }
  50. }

运行结果

  1. 7
  2. =======华丽的分割线========
  3. 最高工资员工为Optional[Person [name=张三, age=18, salary=9999.99, status=FREE]]
  4. =======华丽的分割线========
  5. 最低工资员工为Optional[Person [name=王五, age=28, salary=3333.33, status=BUSY]]

终止操作——归约



map 和 reduce 的连接通常称为 map-reduce 模式,因 Google 用它来进行网络搜索而出名。

代码示例:


  1. package com.xnn.stream;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Optional;
  8. import java.util.stream.Collectors;
  9. import java.util.stream.Stream;
  10. import org.junit.Test;
  11. import com.xnn.lambda.Person;
  12. import com.xnn.lambda.Person.Status;
  13. /**
  14. * 类(接口)描述://中间操作
  15. *
  16. * @author xnn 2018年10月22日下午3:27:12
  17. */
  18. public class TestStreamAPI2 {
  19. List<Person> person = Arrays.asList(
  20. new Person("李四", 59, 6666.66, Status.FREE),
  21. new Person("张三", 18, 9999.99, Status.FREE),
  22. new Person("王五", 28, 3333.33, Status.BUSY),
  23. new Person("赵六", 8, 7777.77, Status.VACATION),
  24. new Person("田七", 38, 5555.55, Status.BUSY),
  25. new Person("田七", 38, 5555.55, Status.VACATION),
  26. new Person("田七", 38, 5555.55, Status.VACATION)
  27. );
  28. /**
  29. * 归约
  30. * 1、reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回 T
  31. * 2、reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 Optional<T>
  32. */
  33. @Test
  34. public void test6() {
  35. // reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值,返回 T
  36. List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  37. /**
  38. * 先把0作为了x,y是流中的第一个元素 相加得1,然后1作为x,流中的第二个元素作为y,就这样,依次加下去。
  39. */
  40. Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
  41. System.out.println(reduce);
  42. System.out.println("=======华丽的分割线========");
  43. // reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 Optional<T>
  44. /**
  45. * 可以看出两个reduce方法返回的并不一样,因为第一个reduce方法有初始值,最后所得的值肯定不会为空,而第二种情况则有可能会为空,所以返回值为跑optional
  46. */
  47. Optional<Double> reduce2 = person.stream().map(Person::getSalary)
  48. .reduce(Double::sum);
  49. System.out.println(reduce2);
  50. System.out.println("=======华丽的分割线========");
  51. }
  52. }

运行结果:

  1. 55
  2. =======华丽的分割线========
  3. Optional[44444.40000000001]
  4. =======华丽的分割线========

终止操作——收集



Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、Map)。

另外, Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下表:





代码示例

  1. package com.xnn.stream;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Map;
  7. import java.util.Optional;
  8. import java.util.stream.Collectors;
  9. import java.util.stream.Stream;
  10. import org.junit.Test;
  11. import com.xnn.lambda.Person;
  12. import com.xnn.lambda.Person.Status;
  13. /**
  14. * 类(接口)描述://中间操作
  15. *
  16. * @author xnn 2018年10月22日下午3:27:12
  17. */
  18. public class TestStreamAPI2 {
  19. List<Person> person = Arrays.asList(
  20. new Person("李四", 59, 6666.66, Status.FREE),
  21. new Person("张三", 18, 9999.99, Status.FREE),
  22. new Person("王五", 28, 3333.33, Status.BUSY),
  23. new Person("赵六", 8, 7777.77, Status.VACATION),
  24. new Person("田七", 38, 5555.55, Status.BUSY),
  25. new Person("田七", 38, 5555.55, Status.VACATION),
  26. new Person("田七", 38, 5555.55, Status.VACATION)
  27. );
  28. /**
  29. * 收集: collect(Collector c) 将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
  30. */
  31. @Test
  32. public void test7() {
  33. //把人员的名字放到一个list中去
  34. List<String> collect = person.stream().map(Person::getName)
  35. .collect(Collectors.toList());
  36. System.out.println(collect);
  37. System.out.println("=======华丽的分割线=======");
  38. //把人员的名字放到一个hashset中去(会自动去重)
  39. HashSet<String> collect2 = person.stream().map(Person::getName)
  40. .collect(Collectors.toCollection(HashSet::new));
  41. System.out.println(collect2);
  42. System.out.println("=======华丽的分割线=======");
  43. //计数
  44. Long long1 = person.stream().collect(Collectors.counting());
  45. System.out.println(long1);
  46. System.out.println("=======华丽的分割线=======");
  47. // 按状态分组
  48. Map<Status, List<Person>> collect3 = person.stream()
  49. .collect(Collectors.groupingBy((e) -> e.getStatus()));
  50. System.out.println(collect3);
  51. System.out.println("=======华丽的分割线=======");
  52. // 多重分组(先按状态分组,再按薪资是否大于5000分组)
  53. Map<Status, Map<Boolean, List<Person>>> collect4 = person.stream()
  54. .collect(Collectors.groupingBy((e) -> e.getStatus(),
  55. Collectors.groupingBy((e) -> e.getSalary() > 5000)));
  56. System.out.println(collect4);
  57. System.out.println("=======华丽的分割线=======");
  58. //取所有人员薪资的平均值
  59. Double double1 = person.stream()
  60. .collect(Collectors.averagingDouble((e) -> e.getSalary()));
  61. System.out.println("所有人员薪资的平均值:"+double1);
  62. System.out.println("=======华丽的分割线=======");
  63. //把所有人的姓名拼接成一个字符串
  64. String collect5 = person.stream().map(Person::getName)
  65. .collect(Collectors.joining());
  66. System.out.println(collect5);
  67. System.out.println("=======华丽的分割线=======");
  68. //找出所有人中薪资最少的一个员工的信息。
  69. Optional<Person> optional = person.stream().collect(Collectors.minBy(
  70. (e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
  71. System.out.println(optional);
  72. System.out.println("=======华丽的分割线=======");
  73. }
  74. }

运行结果

  1. [李四, 张三, 王五, 赵六, 田七, 田七, 田七]
  2. =======华丽的分割线=======
  3. [李四, 张三, 王五, 赵六, 田七]
  4. =======华丽的分割线=======
  5. 7
  6. =======华丽的分割线=======
  7. {BUSY=[Person [name=王五, age=28, salary=3333.33, status=BUSY], Person [name=田七, age=38, salary=5555.55, status=BUSY]], FREE=[Person [name=李四, age=59, salary=6666.66, status=FREE], Person [name=张三, age=18, salary=9999.99, status=FREE]], VACATION=[Person [name=赵六, age=8, salary=7777.77, status=VACATION], Person [name=田七, age=38, salary=5555.55, status=VACATION], Person [name=田七, age=38, salary=5555.55, status=VACATION]]}
  8. =======华丽的分割线=======
  9. {BUSY={false=[Person [name=王五, age=28, salary=3333.33, status=BUSY]], true=[Person [name=田七, age=38, salary=5555.55, status=BUSY]]}, FREE={true=[Person [name=李四, age=59, salary=6666.66, status=FREE], Person [name=张三, age=18, salary=9999.99, status=FREE]]}, VACATION={true=[Person [name=赵六, age=8, salary=7777.77, status=VACATION], Person [name=田七, age=38, salary=5555.55, status=VACATION], Person [name=田七, age=38, salary=5555.55, status=VACATION]]}}
  10. =======华丽的分割线=======
  11. 所有人员薪资的平均值:6349.2
  12. =======华丽的分割线=======
  13. 李四张三王五赵六田七田七田七
  14. =======华丽的分割线=======
  15. Optional[Person [name=王五, age=28, salary=3333.33, status=BUSY]]
  16. =======华丽的分割线=======

Java8新特性——StreamAPI 的使用的更多相关文章

  1. Java8新特性——StreamAPI(二)

    1. 收集器简介 收集器用来将经过筛选.映射的流进行最后的整理,可以使得最后的结果以不同的形式展现. collect方法即为收集器,它接收Collector接口的实现作为具体收集器的收集方法. Col ...

  2. Java8新特性——StreamAPI(一)

    1. 流的基本概念 1.1 什么是流? 流是Java8引入的全新概念,它用来处理集合中的数据,暂且可以把它理解为一种高级集合. 众所周知,集合操作非常麻烦,若要对集合进行筛选.投影,需要写大量的代码, ...

  3. java8 新特性学习笔记

    Java8新特性 学习笔记 1主要内容 Lambda 表达式 函数式接口 方法引用与构造器引用 Stream API 接口中的默认方法与静态方法 新时间日期 API 其他新特性 2 简洁 速度更快 修 ...

  4. 【Java基础】Java8 新特性

    Java8 新特性 Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).使用它可以写出更简洁.更灵活的代码. L ...

  5. java8新特性全面解析

    在Java Code Geeks上有大量的关于Java 8 的教程了,像玩转Java 8--lambda与并发,Java 8 Date Time API 教程: LocalDateTime和在Java ...

  6. Java8新特性

    Java8新特性 Java8主要的新特性涵盖:函数式接口.Lambda 表达式.集合的流式操作.注解的更新.安全性的增强.IO\NIO 的改进.完善的全球化功能等. 1.函数式接口 Java 8 引入 ...

  7. Java系列 - 用Java8新特性进行Java开发太爽了

    本人博客文章网址:https://www.peretang.com/using-java8s-new-features-to-coding-is-awesome/ 前言 从开始写博客到现在已经过去3个 ...

  8. Java8 新特性之Stream----java.util.stream

    这个包主要提供元素的streams函数操作,比如对collections的map,reduce. 例如: int sum = widgets.stream() .filter(b -> b.ge ...

  9. 这可能是史上最好的 Java8 新特性 Stream 流教程

    本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...

随机推荐

  1. springboot热启动中那些不为人知的东东

    在springboot热启动中,大家都知道在pom文件中配置devtools,但是当这个服务特别大,或者引入的包特别多的时候,重启一下就特别慢,如果开发的PC的内存和cpu如果不给里的h话,系统就卡主 ...

  2. Spring5源码解析2-register方法注册配置类

    接上回已经讲完了this()方法,现在来看register(annotatedClasses);方法. // new AnnotationConfigApplicationContext(AppCon ...

  3. PDF目录编辑器使用介绍

    PDF目录编辑器使用介绍 魏刘宏 2019.06.28 PDF 是一个比较优秀的文档格式,能够保证在任何终端显示的样式是一样的.但同时也带来了一个问题,就是编辑不方便,其实这也是这个格式特意为之的,无 ...

  4. 刷抖音太累,教你用Python把高颜值的小姐姐都爬下来慢慢看

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: 星安果.AirPython 目 标 场 景 相信大家平时刷抖音短视频 ...

  5. 【OOM】解决思路

    一.什么是OOM? OOM就是outOfMemory,内存溢出!可能是每一个java人员都能遇到的问题!原因是堆中有太多的存活对象(GC-ROOT可达),占满了堆空间. 二.怎么解决? 1.拿到内存溢 ...

  6. crm-2

    1.分页 web必备的功能 1)批量制造测试数据 定义一个空列表用于存储 orm对象 ,models.表名(字段=...)创建orm对象append到列表 ,使用bulk_create(对象列表)一次 ...

  7. SQL Server中的LEFT、RIGHT函数

    SQL Server中的LEFT.RIGHT函数. LEFT:返回字符串中从左边开始指定个数字符. LEFT(character_expression,integer_expression); RIG ...

  8. 《0day安全软件漏洞分析技术》学习笔记

    最近因为工作需要在看0day的软件漏洞分析,发现这本<0day安全软件漏洞分析技术(第2版)>真是本好书,唯一缺点就是书上的环境是Windows XP 32Bit的,基于现状难以进行实践, ...

  9. GBT22239-2008-等保1.0三级要求

    第三级基本要求 7.1 技术要求 7.1.1 物理安全 7.1.1.1 物理位置的选择(G3) 本项要求包括: a)   机房和办公场地应选择在具有防震.防风和防雨等能力的建筑内: b)   机房场地 ...

  10. Day_04 面向对象

    概述 对于面向对象编程的支持,Go语言设计得非常简洁而优雅.因为,Go语言并没有沿袭传统 面向对象编程中的诸多概念,比如继承(不支持继承,尽管匿名字段的内存布局和行为类似继承,但它并不是继承). 虚函 ...