# SimplifyCoding **Repository Path**: haiweizone/simplify-coding ## Basic Information - **Project Name**: SimplifyCoding - **Description**: 快速编程的技巧 - **Primary Language**: Java - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-05-16 - **Last Updated**: 2021-06-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 一、Stream流式编程 ## 1. 流的使用 ![流式编程PPT截图](帮助文档素材/流的使用PPT截图.png) ![Stream速记](帮助文档素材/Stream速记.png) ```java public class StreamService { /** * 当无状态操作后面跟的是终端操作 * @param cartSkuList */ public void statelessThenTerminal(List cartSkuList) { cartSkuList.stream().peek(sku -> System.out.println(sku.getSkuName())).forEach(sku -> System.out.println(sku.toString())); } } ``` 预期是先执行完所有的peek中的打印名称之后,再执行forEach的打印,但是结果却是: ```text 无人机 Sku(skuId=20210001, skuName=无人机, skuPrice=4599.0, totalNum=10, totalPrice=45990.0, skuCategory=ELECTRONICS) VR一体机 Sku(skuId=20210002, skuName=VR一体机, skuPrice=2500.0, totalNum=3, totalPrice=7500.0, skuCategory=ELECTRONICS) 纯色衬衫 Sku(skuId=20210003, skuName=纯色衬衫, skuPrice=249.0, totalNum=5, totalPrice=1245.0, skuCategory=CLOTHING) 牛仔裤 Sku(skuId=20210004, skuName=牛仔裤, skuPrice=149.0, totalNum=2, totalPrice=298.0, skuCategory=CLOTHING) 跑步机 Sku(skuId=20210005, skuName=跑步机, skuPrice=5500.0, totalNum=7, totalPrice=38500.0, skuCategory=SPORTS) Java编程思想 Sku(skuId=20210006, skuName=Java编程思想, skuPrice=75.0, totalNum=2, totalPrice=150.0, skuCategory=BOOKS) 算法设计 Sku(skuId=20210007, skuName=算法设计, skuPrice=60.0, totalNum=8, totalPrice=400.0, skuCategory=BOOKS) Spring核心 Sku(skuId=20210008, skuName=Spring核心, skuPrice=55.0, totalNum=4, totalPrice=220.0, skuCategory=BOOKS) 系统设计师 Sku(skuId=20210009, skuName=系统设计师, skuPrice=35.25, totalNum=9, totalPrice=317.25, skuCategory=BOOKS) ``` 可见,无状态中间操作+终端操作,会交替执行,或者从另一个角度来看,是每个元素执行完两个操作之后,再循环到下一个元素。 ## 2. 流的构建 ### 2.1 由值创建流 ```java public class StreamConstruct { public void streamFromValues() { Stream intStream = Stream.of(1,2,3,4,5); intStream.forEach(System.out::print); } } ``` ### 2.2 由数组创建流 ```java public class StreamConstruct { public void streamFromArray() { int[] ints = new int[]{1,2,3,4,5}; IntStream intStream = Arrays.stream(ints); intStream.forEach(System.out::print); } } ``` ### 2.3 由文件创建流 ```java public class StreamConstruct { public void streamFromFile() throws URISyntaxException, IOException { Stream fileContents = Files.lines(Paths.get("E:\\JavaSpace\\simplify-coding\\src\\main\\resources")); fileContents.forEach(System.out::print); } } ``` ### 2.4 由函数创建流(无限元素) ```java public class StreamConstruct { public void streamFromFunction() { Stream infinitIntStreamByIterate = Stream.iterate(0, n -> n + 1); infinitIntStreamByIterate.forEach(System.out::println); Stream infinitDoubleStreamByGen = Stream.generate(Math::random); infinitDoubleStreamByGen.forEach(System.out::println); } } ``` ## 3. 收集器简介 将流中的元素累积成一个结果 ,作用于终端操作collect()上 ### 3.1 预定义收集器功能 (1). toList ```java package com.harvey.coding.lambda.stream; import com.harvey.coding.lambda.cart.CartService; import java.util.stream.Collectors; public class StreamCollect { public void toList(){ CartService.getCartSkuList().stream().collect(Collectors.toList()); } } ``` (2). group ```java package com.harvey.coding.lambda.stream; import com.harvey.coding.lambda.cart.CartService; import com.harvey.coding.lambda.cart.Sku; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class StreamCollect { public void groupBy() { Map> groupByResult = CartService.getCartSkuList().stream() .collect(Collectors.groupingBy(s -> s.getSkuCategory())); } } ``` (3). partition 分区是group by的一种特例,因为返回的Map的key只有true和false: ```java package com.harvey.coding.lambda.stream; import com.harvey.coding.lambda.cart.CartService; import com.harvey.coding.lambda.cart.Sku; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class StreamCollect { public void partition() { Map> p = CartService.getCartSkuList().stream() .collect(Collectors.partitioningBy(s -> s.getTotalNum() > 5)); } } ``` 其他的功能可以查看Collectors的源码 # 二、优雅关闭资源 ## 1. 常见需要手动释放的物理资源 手动关闭资源的时候,遵循一定的顺序: 一般情况下是:先打开的后关闭,后打开的先关闭 另一种情况:看依赖关系,如果流a依赖流b,应该先关闭流a,再关闭流b; 使用try-with-resource方式关闭流的条件是实现了AutoCloseable接口 文件/流资源、套接字资源 、数据库连接资源 需要手动关闭的原因是GC无法回收物理资源 ## 2. 资源关闭的特殊情况 ### 2.1 资源对象被`return`的情况下,由调用方进行关闭 ### 2.2 `ByteArrayInputStream`等不需要检查关闭的资源对象 ### 2.3 使用`Socket`获取的`InputStream`和`OutputStream`对象不需要关闭 直接关闭`InputStream`和`OutputStream`会导致`Socket`连接关闭,正确的关闭方式是使用`Socket`的`shutdownInput`和`shutdownOutput`方法 # 三、Guava工具集 ## 1. 使用和避免null *(1) 创建Optional对象: of、ofNullable* *(2) isPresent不建议直接使用,因为和直接空判断没有区别* *(3) ifPresent* *(4) orElse* *(5) orElseGet* *(6) orElseThrow* *(7) map* *(8) filter* *(9) flatMap* ## 2. 不可变集合 JDK中提供的unmonifiableXXX的方法,存在一下缺点: - 笨重 - 不安全 - 低效 使用Guava构造不可变集合的三种方式: *(1) ImmutableXXX.copyOf: 通过已经存在的集合创建* *(2) ImmutableXXX.of: 通过初始值,直接创建不可变集合* *(3) ImmutableXXX.builder的方式* ## 3. 新集合类型 `MultiSet`