Java8 新特性.pdf

参考资料

https://blog.csdn.net/IO_Field/article/details/54971761

https://blog.csdn.net/qq_20989105/article/details/81234175?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2

https://juejin.im/post/5cc124a95188252d891d00f2#heading-13

  1. package com.atguigu.java8;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.Iterator;
  5. import java.util.List;
  6. import java.util.stream.Stream;
  7. import org.junit.Test;
  8. /*
  9. * 一、Stream API 的操作步骤:
  10. *
  11. * 1. 创建 Stream
  12. *
  13. * 2. 中间操作
  14. *
  15. * 3. 终止操作(终端操作)
  16. */
  17. public class TestStreamaAPI {
  18. //1. 创建 Stream
  19. @Test
  20. public void test1(){
  21. //1. Collection 提供了两个方法 stream() 与 parallelStream()
  22. List<String> list = new ArrayList<>();
  23. Stream<String> stream = list.stream(); //获取一个顺序流
  24. Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
  25. //2. 通过 Arrays 中的 stream() 获取一个数组流
  26. Integer[] nums = new Integer[10];
  27. Stream<Integer> stream1 = Arrays.stream(nums);
  28. //3. 通过 Stream 类中静态方法 of()
  29. Stream<Integer> stream2 = Stream.of(1,2,3,4,5,6);
  30. //4. 创建无限流
  31. //迭代
  32. Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2).limit(10);
  33. stream3.forEach(System.out::println);
  34. //生成
  35. Stream<Double> stream4 = Stream.generate(Math::random).limit(2);
  36. stream4.forEach(System.out::println);
  37. }
  38. //2. 中间操作
  39. List<Employee> emps = Arrays.asList(
  40. new Employee(102, "李四", 59, 6666.66),
  41. new Employee(101, "张三", 18, 9999.99),
  42. new Employee(103, "王五", 28, 3333.33),
  43. new Employee(104, "赵六", 8, 7777.77),
  44. new Employee(104, "赵六", 8, 7777.77),
  45. new Employee(104, "赵六", 8, 7777.77),
  46. new Employee(105, "田七", 38, 5555.55)
  47. );
  48. /*
  49. 筛选与切片
  50. filter——接收 Lambda , 从流中排除某些元素。
  51. limit——截断流,使其元素不超过给定数量。
  52. skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
  53. distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
  54. */
  55. //内部迭代:迭代操作 Stream API 内部完成
  56. @Test
  57. public void test2(){
  58. //所有的中间操作不会做任何的处理
  59. Stream<Employee> stream = emps.stream()
  60. .filter((e) -> {
  61. System.out.println("测试中间操作");
  62. return e.getAge() <= 35;
  63. });
  64. //只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”
  65. stream.forEach(System.out::println);
  66. }
  67. //外部迭代
  68. @Test
  69. public void test3(){
  70. Iterator<Employee> it = emps.iterator();
  71. while(it.hasNext()){
  72. System.out.println(it.next());
  73. }
  74. }
  75. @Test
  76. public void test4(){
  77. emps.stream()
  78. .filter((e) -> {
  79. System.out.println("短路!"); // && ||
  80. return e.getSalary() >= 5000;
  81. }).limit(3)
  82. .forEach(System.out::println);
  83. }
  84. @Test
  85. public void test5(){
  86. emps.parallelStream()
  87. .filter((e) -> e.getSalary() >= 5000)
  88. .skip(2)
  89. .forEach(System.out::println);
  90. }
  91. @Test
  92. public void test6(){
  93. emps.stream()
  94. .distinct()
  95. .forEach(System.out::println);
  96. }
  97. }
  98. public class TestStreamAPI1 {
  99. List<Employee> emps = Arrays.asList(
  100. new Employee(102, "李四", 59, 6666.66),
  101. new Employee(101, "张三", 18, 9999.99),
  102. new Employee(103, "王五", 28, 3333.33),
  103. new Employee(104, "赵六", 8, 7777.77),
  104. new Employee(104, "赵六", 8, 7777.77),
  105. new Employee(104, "赵六", 8, 7777.77),
  106. new Employee(105, "田七", 38, 5555.55)
  107. );
  108. //2. 中间操作
  109. /*
  110. 映射
  111. map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  112. flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
  113. */
  114. @Test
  115. public void test1(){
  116. Stream<String> str = emps.stream()
  117. .map((e) -> e.getName());
  118. System.out.println("-------------------------------------------");
  119. List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
  120. Stream<String> stream = strList.stream()
  121. .map(String::toUpperCase);
  122. stream.forEach(System.out::println);
  123. Stream<Stream<Character>> stream2 = strList.stream()
  124. .map(TestStreamAPI1::filterCharacter);
  125. stream2.forEach((sm) -> {
  126. sm.forEach(System.out::println);
  127. });
  128. System.out.println("---------------------------------------------");
  129. Stream<Character> stream3 = strList.stream()
  130. .flatMap(TestStreamAPI1::filterCharacter);
  131. stream3.forEach(System.out::println);
  132. }
  133. public static Stream<Character> filterCharacter(String str){
  134. List<Character> list = new ArrayList<>();
  135. for (Character ch : str.toCharArray()) {
  136. list.add(ch);
  137. }
  138. return list.stream();
  139. }
  140. /*
  141. sorted()——自然排序
  142. sorted(Comparator com)——定制排序
  143. */
  144. @Test
  145. public void test2(){
  146. emps.stream()
  147. .map(Employee::getName)
  148. .sorted()
  149. .forEach(System.out::println);
  150. System.out.println("------------------------------------");
  151. emps.stream()
  152. .sorted((x, y) -> {
  153. if(x.getAge() == y.getAge()){
  154. return x.getName().compareTo(y.getName());
  155. }else{
  156. return Integer.compare(x.getAge(), y.getAge());
  157. }
  158. }).forEach(System.out::println);
  159. }
  160. }
  161. package com.atguigu.java8;
  162. import java.util.Arrays;
  163. import java.util.List;
  164. import java.util.Optional;
  165. import java.util.stream.Stream;
  166. import org.junit.Test;
  167. import com.atguigu.java8.Employee.Status;
  168. /*
  169. * 一、 Stream 的操作步骤
  170. *
  171. * 1. 创建 Stream
  172. *
  173. * 2. 中间操作
  174. *
  175. * 3. 终止操作
  176. */
  177. public class TestStreamAPI2 {
  178. List<Employee> emps = Arrays.asList(
  179. new Employee(102, "李四", 59, 6666.66, Status.BUSY),
  180. new Employee(101, "张三", 18, 9999.99, Status.FREE),
  181. new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
  182. new Employee(104, "赵六", 8, 7777.77, Status.BUSY),
  183. new Employee(104, "赵六", 8, 7777.77, Status.FREE),
  184. new Employee(104, "赵六", 8, 7777.77, Status.FREE),
  185. new Employee(105, "田七", 38, 5555.55, Status.BUSY)
  186. );
  187. //3. 终止操作
  188. /*
  189. allMatch——检查是否匹配所有元素
  190. anyMatch——检查是否至少匹配一个元素
  191. noneMatch——检查是否没有匹配的元素
  192. findFirst——返回第一个元素
  193. findAny——返回当前流中的任意元素
  194. count——返回流中元素的总个数
  195. max——返回流中最大值
  196. min——返回流中最小值
  197. */
  198. @Test
  199. public void test1(){
  200. boolean bl = emps.stream()
  201. .allMatch((e) -> e.getStatus().equals(Status.BUSY));
  202. System.out.println(bl);
  203. boolean bl1 = emps.stream()
  204. .anyMatch((e) -> e.getStatus().equals(Status.BUSY));
  205. System.out.println(bl1);
  206. boolean bl2 = emps.stream()
  207. .noneMatch((e) -> e.getStatus().equals(Status.BUSY));
  208. System.out.println(bl2);
  209. }
  210. @Test
  211. public void test2(){
  212. Optional<Employee> op = emps.stream()
  213. .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
  214. .findFirst();
  215. System.out.println(op.get());
  216. System.out.println("--------------------------------");
  217. Optional<Employee> op2 = emps.parallelStream()
  218. .filter((e) -> e.getStatus().equals(Status.FREE))
  219. .findAny();
  220. System.out.println(op2.get());
  221. }
  222. @Test
  223. public void test3(){
  224. long count = emps.stream()
  225. .filter((e) -> e.getStatus().equals(Status.FREE))
  226. .count();
  227. System.out.println(count);
  228. Optional<Double> op = emps.stream()
  229. .map(Employee::getSalary)
  230. .max(Double::compare);
  231. System.out.println(op.get());
  232. Optional<Employee> op2 = emps.stream()
  233. .min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
  234. System.out.println(op2.get());
  235. }
  236. //注意:流进行了终止操作后,不能再次使用
  237. @Test
  238. public void test4(){
  239. Stream<Employee> stream = emps.stream()
  240. .filter((e) -> e.getStatus().equals(Status.FREE));
  241. long count = stream.count();
  242. stream.map(Employee::getSalary)
  243. .max(Double::compare);
  244. }
  245. }
  246. package com.atguigu.java8;
  247. public class Employee {
  248. private int id;
  249. private String name;
  250. private int age;
  251. private double salary;
  252. private Status status;
  253. public Employee() {
  254. }
  255. public Employee(String name) {
  256. this.name = name;
  257. }
  258. public Employee(String name, int age) {
  259. this.name = name;
  260. this.age = age;
  261. }
  262. public Employee(int id, String name, int age, double salary) {
  263. this.id = id;
  264. this.name = name;
  265. this.age = age;
  266. this.salary = salary;
  267. }
  268. public Employee(int id, String name, int age, double salary, Status status) {
  269. this.id = id;
  270. this.name = name;
  271. this.age = age;
  272. this.salary = salary;
  273. this.status = status;
  274. }
  275. public Status getStatus() {
  276. return status;
  277. }
  278. public void setStatus(Status status) {
  279. this.status = status;
  280. }
  281. public int getId() {
  282. return id;
  283. }
  284. public void setId(int id) {
  285. this.id = id;
  286. }
  287. public String getName() {
  288. return name;
  289. }
  290. public void setName(String name) {
  291. this.name = name;
  292. }
  293. public int getAge() {
  294. return age;
  295. }
  296. public void setAge(int age) {
  297. this.age = age;
  298. }
  299. public double getSalary() {
  300. return salary;
  301. }
  302. public void setSalary(double salary) {
  303. this.salary = salary;
  304. }
  305. public String show() {
  306. return "测试方法引用!";
  307. }
  308. @Override
  309. public int hashCode() {
  310. final int prime = 31;
  311. int result = 1;
  312. result = prime * result + age;
  313. result = prime * result + id;
  314. result = prime * result + ((name == null) ? 0 : name.hashCode());
  315. long temp;
  316. temp = Double.doubleToLongBits(salary);
  317. result = prime * result + (int) (temp ^ (temp >>> 32));
  318. return result;
  319. }
  320. @Override
  321. public boolean equals(Object obj) {
  322. if (this == obj)
  323. return true;
  324. if (obj == null)
  325. return false;
  326. if (getClass() != obj.getClass())
  327. return false;
  328. Employee other = (Employee) obj;
  329. if (age != other.age)
  330. return false;
  331. if (id != other.id)
  332. return false;
  333. if (name == null) {
  334. if (other.name != null)
  335. return false;
  336. } else if (!name.equals(other.name))
  337. return false;
  338. if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
  339. return false;
  340. return true;
  341. }
  342. @Override
  343. public String toString() {
  344. return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", status=" + status
  345. + "]";
  346. }
  347. public enum Status {
  348. FREE, BUSY, VOCATION;
  349. }
  350. }
  351. public class TestStreamAPI3 {
  352. List<Employee> emps = Arrays.asList(
  353. new Employee(102, "李四", 79, 6666.66, Status.BUSY),
  354. new Employee(101, "张三", 18, 9999.99, Status.FREE),
  355. new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
  356. new Employee(104, "赵六", 8, 7777.77, Status.BUSY),
  357. new Employee(104, "赵六", 8, 7777.77, Status.FREE),
  358. new Employee(104, "赵六", 8, 7777.77, Status.FREE),
  359. new Employee(105, "田七", 38, 5555.55, Status.BUSY)
  360. );
  361. //3. 终止操作
  362. /*
  363. 归约
  364. reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。
  365. */
  366. @Test
  367. public void test1(){
  368. List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
  369. Integer sum = list.stream()
  370. .reduce(0, (x, y) -> x + y);
  371. System.out.println(sum);
  372. System.out.println("----------------------------------------");
  373. Optional<Double> op = emps.stream()
  374. .map(Employee::getSalary)
  375. .reduce(Double::sum);
  376. System.out.println(op.get());
  377. }
  378. //需求:搜索名字中 “六” 出现的次数
  379. @Test
  380. public void test2(){
  381. Optional<Integer> sum = emps.stream()
  382. .map(Employee::getName)
  383. .flatMap(TestStreamAPI1::filterCharacter)
  384. .map((ch) -> {
  385. if(ch.equals('六'))
  386. return 1;
  387. else
  388. return 0;
  389. }).reduce(Integer::sum);
  390. System.out.println(sum.get());
  391. }
  392. //collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
  393. @Test
  394. public void test3(){
  395. List<String> list = emps.stream()
  396. .map(Employee::getName)
  397. .collect(Collectors.toList());
  398. list.forEach(System.out::println);
  399. System.out.println("----------------------------------");
  400. Set<String> set = emps.stream()
  401. .map(Employee::getName)
  402. .collect(Collectors.toSet());
  403. set.forEach(System.out::println);
  404. System.out.println("----------------------------------");
  405. HashSet<String> hs = emps.stream()
  406. .map(Employee::getName)
  407. .collect(Collectors.toCollection(HashSet::new));
  408. hs.forEach(System.out::println);
  409. }
  410. @Test
  411. public void test4(){
  412. Optional<Double> max = emps.stream()
  413. .map(Employee::getSalary)
  414. .collect(Collectors.maxBy(Double::compare));
  415. System.out.println(max.get());
  416. Optional<Employee> op = emps.stream()
  417. .collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
  418. System.out.println(op.get());
  419. Double sum = emps.stream()
  420. .collect(Collectors.summingDouble(Employee::getSalary));
  421. System.out.println(sum);
  422. Double avg = emps.stream()
  423. .collect(Collectors.averagingDouble(Employee::getSalary));
  424. System.out.println(avg);
  425. Long count = emps.stream()
  426. .collect(Collectors.counting());
  427. System.out.println(count);
  428. System.out.println("--------------------------------------------");
  429. DoubleSummaryStatistics dss = emps.stream()
  430. .collect(Collectors.summarizingDouble(Employee::getSalary));
  431. System.out.println(dss.getMax());
  432. }
  433. //分组
  434. @Test
  435. public void test5(){
  436. Map<Status, List<Employee>> map = emps.stream()
  437. .collect(Collectors.groupingBy(Employee::getStatus));
  438. System.out.println(map);
  439. }
  440. //多级分组
  441. @Test
  442. public void test6(){
  443. Map<Status, Map<String, List<Employee>>> map = emps.stream()
  444. .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
  445. if(e.getAge() >= 60)
  446. return "老年";
  447. else if(e.getAge() >= 35)
  448. return "中年";
  449. else
  450. return "成年";
  451. })));
  452. System.out.println(map);
  453. }
  454. //分区
  455. @Test
  456. public void test7(){
  457. Map<Boolean, List<Employee>> map = emps.stream()
  458. .collect(Collectors.partitioningBy((e) -> e.getSalary() >= 5000));
  459. System.out.println(map);
  460. }
  461. //
  462. @Test
  463. public void test8(){
  464. String str = emps.stream()
  465. .map(Employee::getName)
  466. .collect(Collectors.joining("," , "----", "----"));
  467. System.out.println(str);
  468. }
  469. @Test
  470. public void test9(){
  471. Optional<Double> sum = emps.stream()
  472. .map(Employee::getSalary)
  473. .collect(Collectors.reducing(Double::sum));
  474. System.out.println(sum.get());
  475. }
  476. }
package com.atguigu.exer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

import org.junit.Before;
import org.junit.Test;

public class TestTransaction {

    List<Transaction> transactions = null;

    @Before
    public void before(){
        Trader raoul = new Trader("Raoul", "Cambridge");
        Trader mario = new Trader("Mario", "Milan");
        Trader alan = new Trader("Alan", "Cambridge");
        Trader brian = new Trader("Brian", "Cambridge");

        transactions = Arrays.asList(
                new Transaction(brian, 2011, 300),
                new Transaction(raoul, 2012, 1000),
                new Transaction(raoul, 2011, 400),
                new Transaction(mario, 2012, 710),
                new Transaction(mario, 2012, 700),
                new Transaction(alan, 2012, 950)
        );
    }

    //1. 找出2011年发生的所有交易, 并按交易额排序(从低到高)
    @Test
    public void test1(){
        transactions.stream()
                    .filter((t) -> t.getYear() == 2011)
                    .sorted((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()))
                    .forEach(System.out::println);
    }

    //2. 交易员都在哪些不同的城市工作过?
    @Test
    public void test2(){
        transactions.stream()
                    .map((t) -> t.getTrader().getCity())
                    .distinct()
                    .forEach(System.out::println);
    }

    //3. 查找所有来自剑桥的交易员,并按姓名排序
    @Test
    public void test3(){
        transactions.stream()
                    .filter((t) -> t.getTrader().getCity().equals("Cambridge"))
                    .map(Transaction::getTrader)
                    .sorted((t1, t2) -> t1.getName().compareTo(t2.getName()))
                    .distinct()
                    .forEach(System.out::println);
    }

    //4. 返回所有交易员的姓名字符串,按字母顺序排序
    @Test
    public void test4(){
        transactions.stream()
                    .map((t) -> t.getTrader().getName())
                    .sorted()
                    .forEach(System.out::println);

        System.out.println("-----------------------------------");

        String str = transactions.stream()
                    .map((t) -> t.getTrader().getName())
                    .sorted()
                    .reduce("", String::concat);

        System.out.println(str);

        System.out.println("------------------------------------");

        transactions.stream()
                    .map((t) -> t.getTrader().getName())
                    .flatMap(TestTransaction::filterCharacter)
                    .sorted((s1, s2) -> s1.compareToIgnoreCase(s2))
                    .forEach(System.out::print);
    }

    public static Stream<String> filterCharacter(String str){
        List<String> list = new ArrayList<>();

        for (Character ch : str.toCharArray()) {
            list.add(ch.toString());
        }

        return list.stream();
    }

    //5. 有没有交易员是在米兰工作的?
    @Test
    public void test5(){
        boolean bl = transactions.stream()
                    .anyMatch((t) -> t.getTrader().getCity().equals("Milan"));

        System.out.println(bl);
    }


    //6. 打印生活在剑桥的交易员的所有交易额
    @Test
    public void test6(){
        Optional<Integer> sum = transactions.stream()
                    .filter((e) -> e.getTrader().getCity().equals("Cambridge"))
                    .map(Transaction::getValue)
                    .reduce(Integer::sum);

        System.out.println(sum.get());
    }


    //7. 所有交易中,最高的交易额是多少
    @Test
    public void test7(){
        Optional<Integer> max = transactions.stream()
                    .map((t) -> t.getValue())
                    .max(Integer::compare);

        System.out.println(max.get());
    }

    //8. 找到交易额最小的交易
    @Test
    public void test8(){
        Optional<Transaction> op = transactions.stream()
                    .min((t1, t2) -> Integer.compare(t1.getValue(), t2.getValue()));

        System.out.println(op.get());
    }

}





package com.atguigu.exer;
//交易员类
public class Trader {

    private String name;
    private String city;

    public Trader() {
    }

    public Trader(String name, String city) {
        this.name = name;
        this.city = city;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "Trader [name=" + name + ", city=" + city + "]";
    }

}


package com.atguigu.exer;
//交易类
public class Transaction {

    private Trader trader;
    private int year;
    private int value;

    public Transaction() {
    }

    public Transaction(Trader trader, int year, int value) {
        this.trader = trader;
        this.year = year;
        this.value = value;
    }

    public Trader getTrader() {
        return trader;
    }

    public void setTrader(Trader trader) {
        this.trader = trader;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Transaction [trader=" + trader + ", year=" + year + ", value="
                + value + "]";
    }

}

定义

Stream(流)是一个来自数据源的元素队列
元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
数据源 流的来源。 可以是集合,数组 等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:

  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent

style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。

  • 内部迭代: 以前对集合遍历都是通过Iterator或者增强for的方式, 显式的在集合外部进行迭代, 这叫做外部迭

代。 Stream提供了内部迭代的方式,流可以直接调用遍历方法。
当使用一个流的时候,通常包括三个基本步骤:获取一个数据源(source)→ 数据转换→执行操作获取想要的结
果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以
像链条一样排列,变成一个管道

获取流

java.util.stream.Stream 是Java 8新加入的最常用的流接口。(这并不是一个函数式接口。)
获取一个流非常简单,有以下几种常用的方式:
所有的 Collection 集合都可以通过 stream 默认方法获取流;
Stream 接口的静态方法 of 可以获取数组对应的流。

ArrayList<Object> list = new ArrayList<>();
Stream<Object> stream1 = list.stream();

HashSet<Object> sets = new HashSet<>();
Stream<Object> stream2 = sets.stream();

HashMap<String, String> map = new HashMap<>();
Set<String> keysets = map.keySet();
Stream<String> stream3 = keysets.stream();

Collection<String> values = map.values();
Stream<String> stream4 = values.stream();

Set<Map.Entry<String, String>> entries = map.entrySet();
Stream<Map.Entry<String, String>> stream5 = entries.stream();

//数组
Integer[] arr = {1,2,3,4,5,6};
Stream<Integer> arr1 = Stream.of(arr);

常用方法

流模型的操作很丰富,这里介绍一些常用的API。这些方法可以被分成两种:

  • 延迟方法:返回值类型仍然是 Stream 接口自身类型的方法,因此支持链式调用。(除了终结方法外,其余方

法均为延迟方法。)

  • 终结方法:返回值类型不再是 Stream 接口自身类型的方法,因此不再支持类似 StringBuilder 那样的链式调

用。本小节中,终结方法包括 count 和 forEach 方法。

foreach

虽然方法名字叫 forEach ,但是与for循环中的“for-each”昵称不同。

void forEach(Consumer<? super T> action);

该方法接收一个 Consumer 接口函数,会将每一个流元素交给该函数进行处理
Stream流中的常用方法_forEach
void forEach(Consumer<? super T> action);
该方法接收一个Consumer接口函数,会将每一个流元素交给该函数进行处理。
Consumer接口是一个消费型的函数式接口,可以传递Lambda表达式,消费数据
简单记:
forEach方法,用来遍历流中的数据
是一个终结方法,遍历之后就不能继续调用Stream流中的其他方法

Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六", "田七");
//使用Stream流中的方法forEach对Stream流中的数据进行遍历
stream.forEach(name->System.out.println(name));

filter

Stream流中的常用方法_filter:用于对Stream流中的数据进行过滤
Stream filter(Predicate<? super T> predicate);
filter方法的参数Predicate是一个函数式接口,所以可以传递Lambda表达式,对数据进行过滤
Predicate中的抽象方法:
boolean test(T t);

//创建一个Stream流
Stream<String> stream = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
//对Stream流中的元素进行过滤,只要姓张的人
Stream<String> stream2 = stream.filter((String name)->{return name.startsWith("张");});
//遍历stream2流
stream2.forEach(name-> System.out.println(name));

/*
     Stream流属于管道流,只能被消费(使用)一次
     第一个Stream流调用完毕方法,数据就会流转到下一个Stream上
     而这时第一个Stream流已经使用完毕,就会关闭了
     所以第一个Stream流就不能再调用方法了
     IllegalStateException: stream has already been operated upon or closed
*/
//遍历stream流
stream.forEach(name-> System.out.println(name));

map

image.png

//获取一个String类型的Stream流
Stream<String> stream = Stream.of("1", "2", "3", "4");
//使用map方法,把字符串类型的整数,转换(映射)为Integer类型的整数
Stream<Integer> stream2 = stream.map((String s)->{
    return Integer.parseInt(s);
});
//遍历Stream2流
stream2.forEach(i-> System.out.println(i));

count

正如旧集合 Collection 当中的 size 方法一样,流提供 count 方法来数一数其中的元素个数
long count();
该方法返回一个long值代表元素个数(不再像旧集合那样是int值)

ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
list.add(6);
list.add(7);
Stream<Integer> stream = list.stream();
long count = stream.count();
System.out.println(count);//7

limit

Stream流中的常用方法_limit:用于截取流中的元素
limit方法可以对流进行截取,只取用前n个。方法签名:
Stream limit(long maxSize);
参数是一个long型,如果集合当前长度大于参数则进行截取;否则不进行操作
limit方法是一个延迟方法,只是对流中的元素进行截取,返回的是一个新的流,所以可以继续调用Stream流中的其他方法

//获取一个Stream流
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream = Stream.of(arr);
//使用limit对Stream流中的元素进行截取,只要前3个元素
Stream<String> stream2 = stream.limit(3);
//遍历stream2流
stream2.forEach(name-> System.out.println(name));

skip

Stream流中的常用方法_skip:用于跳过元素
如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流:
Stream skip(long n);
如果流的当前长度大于n,则跳过前n个;否则将会得到一个长度为0的空流。

//获取一个Stream流
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream = Stream.of(arr);
//使用skip方法跳过前3个元素
Stream<String> stream2 = stream.skip(3);
//遍历stream2流
stream2.forEach(name-> System.out.println(name));

concat

Stream流中的常用方法_concat:用于把流组合到一起
如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat
static Stream concat(Stream<? extends T> a, Stream<? extends T> b)

 Stream<String> stream1 = Stream.of("张三丰", "张翠山", "赵敏", "周芷若", "张无忌");
//获取一个Stream流
String[] arr = {"美羊羊","喜洋洋","懒洋洋","灰太狼","红太狼"};
Stream<String> stream2 = Stream.of(arr);
//把以上两个流组合为一个流
Stream<String> concat = Stream.concat(stream1, stream2);
//遍历concat流
concat.forEach(name-> System.out.println(name));

案例

  1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
  2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
  3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
  4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
  5. 将两个队伍合并为一个队伍;存储到一个新集合中。
  6. 根据姓名创建 Person 对象;存储到一个新集合中。
  7. 打印整个队伍的Person对象信息
//第一支队伍
ArrayList<String> one = new ArrayList<>();
one.add("迪丽热巴");
one.add("宋远桥");
one.add("苏星河");
one.add("石破天");
one.add("石中玉");
one.add("老子");
one.add("庄子");
one.add("洪七公");
//1. 第一个队伍只要名字为3个字的成员姓名;存储到一个新集合中。
//2. 第一个队伍筛选之后只要前3个人;存储到一个新集合中。
Stream<String> oneStream = one.stream().filter(name -> name.length() == 3).limit(3);

//第二支队伍
ArrayList<String> two = new ArrayList<>();
two.add("古力娜扎");
two.add("张无忌");
two.add("赵丽颖");
two.add("张三丰");
two.add("尼古拉斯赵四");
two.add("张天爱");
two.add("张二狗");
//3. 第二个队伍只要姓张的成员姓名;存储到一个新集合中。
//4. 第二个队伍筛选之后不要前2个人;存储到一个新集合中。
Stream<String> twoStream = two.stream().filter(name -> name.startsWith("张")).skip(2);

//5. 将两个队伍合并为一个队伍;存储到一个新集合中。
//6. 根据姓名创建Person对象;存储到一个新集合中。
//7. 打印整个队伍的Person对象信息。
Stream.concat(oneStream,twoStream).map(name->new Person(name)).forEach(p-> System.out.println(p));

并行流和串行流

package com.atguigu.java8;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.LongStream;

import org.junit.Test;

public class TestForkJoin {

    @Test
    public void test1(){
        long start = System.currentTimeMillis();

        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinCalculate(0L, 10000000000L);

        long sum = pool.invoke(task);
        System.out.println(sum);

        long end = System.currentTimeMillis();

        System.out.println("耗费的时间为: " + (end - start)); //112-1953-1988-2654-2647-20663-113808
    }

    @Test
    public void test2(){
        long start = System.currentTimeMillis();

        long sum = 0L;

        for (long i = 0L; i <= 10000000000L; i++) {
            sum += i;
        }

        System.out.println(sum);

        long end = System.currentTimeMillis();

        System.out.println("耗费的时间为: " + (end - start)); //34-3174-3132-4227-4223-31583
    }

    @Test
    public void test3(){
        long start = System.currentTimeMillis();

        Long sum = LongStream.rangeClosed(0L, 10000000000L)
                             .parallel()
                             .sum();

        System.out.println(sum);

        long end = System.currentTimeMillis();

        System.out.println("耗费的时间为: " + (end - start)); //2061-2053-2086-18926
    }

}


package com.atguigu.java8;

import java.util.concurrent.RecursiveTask;

public class ForkJoinCalculate extends RecursiveTask<Long>{

    /**
     * 
     */
    private static final long serialVersionUID = 13475679780L;

    private long start;
    private long end;

    private static final long THRESHOLD = 10000L; //临界值

    public ForkJoinCalculate(long start, long end) {
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long length = end - start;

        if(length <= THRESHOLD){
            long sum = 0;

            for (long i = start; i <= end; i++) {
                sum += i;
            }

            return sum;
        }else{
            long middle = (start + end) / 2;

            ForkJoinCalculate left = new ForkJoinCalculate(start, middle);
            left.fork(); //拆分,并将该子任务压入线程队列

            ForkJoinCalculate right = new ForkJoinCalculate(middle+1, end);
            right.fork();

            return left.join() + right.join();
        }

    }

}

ParallelStream

https://cloud.tencent.com/developer/article/1139580

Optional

http://ckjava.com/2019/06/22/understand-Java-8-Optional/

https://rebill.github.io/2018/12/26/java-8-optional/

https://juejin.im/post/6844903945714794503

Time

https://juejin.im/post/6844903807889965070

https://blog.csdn.net/azhong148/article/details/78324325

https://www.jianshu.com/p/19bd58b30660

https://blog.csdn.net/u014044812/article/details/79231738

http://ifeve.com/20-examples-of-date-and-time-api-from-java8/

package com.atguigu.java8;

import java.time.DayOfWeek;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Set;

import org.junit.Test;

public class TestLocalDateTime {

    //6.ZonedDate、ZonedTime、ZonedDateTime : 带时区的时间或日期
    @Test
    public void test7(){
        LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
        System.out.println(ldt);

        ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("US/Pacific"));
        System.out.println(zdt);
    }

    @Test
    public void test6(){
        Set<String> set = ZoneId.getAvailableZoneIds();
        set.forEach(System.out::println);
    }


    //5. DateTimeFormatter : 解析和格式化日期或时间
    @Test
    public void test5(){
//        DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE;

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss E");

        LocalDateTime ldt = LocalDateTime.now();
        String strDate = ldt.format(dtf);

        System.out.println(strDate);

        LocalDateTime newLdt = ldt.parse(strDate, dtf);
        System.out.println(newLdt);
    }

    //4. TemporalAdjuster : 时间校正器
    @Test
    public void test4(){
    LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);

        LocalDateTime ldt2 = ldt.withDayOfMonth(10);
        System.out.println(ldt2);

        LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
        System.out.println(ldt3);

        //自定义:下一个工作日
        LocalDateTime ldt5 = ldt.with((l) -> {
            LocalDateTime ldt4 = (LocalDateTime) l;

            DayOfWeek dow = ldt4.getDayOfWeek();

            if(dow.equals(DayOfWeek.FRIDAY)){
                return ldt4.plusDays(3);
            }else if(dow.equals(DayOfWeek.SATURDAY)){
                return ldt4.plusDays(2);
            }else{
                return ldt4.plusDays(1);
            }
        });

        System.out.println(ldt5);

    }

    //3.
    //Duration : 用于计算两个“时间”间隔
    //Period : 用于计算两个“日期”间隔
    @Test
    public void test3(){
        Instant ins1 = Instant.now();

        System.out.println("--------------------");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }

        Instant ins2 = Instant.now();

        System.out.println("所耗费时间为:" + Duration.between(ins1, ins2));

        System.out.println("----------------------------------");

        LocalDate ld1 = LocalDate.now();
        LocalDate ld2 = LocalDate.of(2011, 1, 1);

        Period pe = Period.between(ld2, ld1);
        System.out.println(pe.getYears());
        System.out.println(pe.getMonths());
        System.out.println(pe.getDays());
    }

    //2. Instant : 时间戳。 (使用 Unix 元年  1970年1月1日 00:00:00 所经历的毫秒值)
    @Test
    public void test2(){
        Instant ins = Instant.now();  //默认使用 UTC 时区
        System.out.println(ins);

        OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));
        System.out.println(odt);

        System.out.println(ins.getNano());

        Instant ins2 = Instant.ofEpochSecond(5);
        System.out.println(ins2);
    }

    //1. LocalDate、LocalTime、LocalDateTime
    @Test
    public void test1(){
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println(ldt);

        LocalDateTime ld2 = LocalDateTime.of(2016, 11, 21, 10, 10, 10);
        System.out.println(ld2);

        LocalDateTime ldt3 = ld2.plusYears(20);
        System.out.println(ldt3);

        LocalDateTime ldt4 = ld2.minusMonths(2);
        System.out.println(ldt4);

        System.out.println(ldt.getYear());
        System.out.println(ldt.getMonthValue());
        System.out.println(ldt.getDayOfMonth());
        System.out.println(ldt.getHour());
        System.out.println(ldt.getMinute());
        System.out.println(ldt.getSecond());
    }

}


package com.atguigu.java8;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TestSimpleDateFormat {

    public static void main(String[] args) throws Exception {

        /*SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

        Callable<Date> task = new Callable<Date>() {

            @Override
            public Date call() throws Exception {
                return sdf.parse("20161121");
            }

        };

        ExecutorService pool = Executors.newFixedThreadPool(10);

        List<Future<Date>> results = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            results.add(pool.submit(task));
        }

        for (Future<Date> future : results) {
            System.out.println(future.get());
        }

        pool.shutdown();*/

        //解决多线程安全问题
        /*Callable<Date> task = new Callable<Date>() {

            @Override
            public Date call() throws Exception {
                return DateFormatThreadLocal.convert("20161121");
            }

        };

        ExecutorService pool = Executors.newFixedThreadPool(10);

        List<Future<Date>> results = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            results.add(pool.submit(task));
        }

        for (Future<Date> future : results) {
            System.out.println(future.get());
        }

        pool.shutdown();*/

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMdd");

        Callable<LocalDate> task = new Callable<LocalDate>() {

            @Override
            public LocalDate call() throws Exception {
                LocalDate ld = LocalDate.parse("20161121", dtf);
                return ld;
            }

        };

        ExecutorService pool = Executors.newFixedThreadPool(10);

        List<Future<LocalDate>> results = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            results.add(pool.submit(task));
        }

        for (Future<LocalDate> future : results) {
            System.out.println(future.get());
        }

        pool.shutdown();
    }

}