Skip to content

Commit

Permalink
2020/9/23
Browse files Browse the repository at this point in the history
  • Loading branch information
wangdonghao committed Sep 23, 2020
1 parent 32c82a6 commit 3557340
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 80 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
- [Spring AOP](javaee/spring/SpringAOP.md)
- [Spring Controller](javaee/spring/SpringController.md)
- [Spring Session](javaee/spring/SpringSession.md)
- [Spring Security](javaee/spring/SpringSecurity.md)

## 其它

Expand Down
80 changes: 47 additions & 33 deletions javase/容器/stream.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,51 @@

流处理是对运动中的数据的处理,在生成或接收数据时直接计算数据。应用程序中分析和查询不断存在,数据不断地流经它们。在从流中接收到事件时,流处理应用程序对该事件作出反应。

如果我们使用传统的循环迭代方式对数据集进行复杂计算,常常会带来两个弊端:

1. 迭代次数多,迭代次数跟函数调用的次数相等。
2. 频繁产生中间结果,存储开销无法接受。

流处理可以立即对事件做出反应,且可以处理比其他数据处理系统大得多的数据量:直接处理事件流,并且只保留数据中有意义的子集。尤其是面对持续生成,本质上是无穷尽的数据集。


### Java Stream 类

JDK 1.8 新增。将要处理的元素集合看作一种流,在管道的节点上进行处理。使代码更简洁易读。

```java
List<Integer> transactionsIds =
widgets.stream() // 声明作为流处理
.filter(b -> b.getColor() == RED) // 过滤
.sorted((x,y) -> x.getWeight() - y.getWeight()) // 排序
.mapToInt(Widget::getWeight) // 转化
.sum(); // 汇总
```


---
集合接口有两个方法来生成流,数据类型将由 Collection 转化为 Stream 。

## 流操作
- `stream` 方法:为集合创建串行流。
- `parallelStream` 方法:为集合创建并行流。

### 生成流 stream
1. Stream 的遍历方式和结果与 Iterator 无差别(便于转化),其优势在于其原型链的设计使得它可以对遍历处理后的数据进行再处理。

集合接口有两个方法来生成流,数据类型将由 List 转化为 Stream
2. parallelStream 提供了流的并行处理,底层使用 Fork/Join 框架,简单理解就是多线程异步任务的一种实现。处理过程中会有多个线程处理元素,具体由 JDK 负责管理。不保证有序性

- `stream` 方法:为集合创建串行流。
- `parallelStream` 方法:为集合创建并行流。
3. 串行流和并行流之间可以通过 `parallel``sequential` 方法相互转化。

```java
// 获取空字符串的数量
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
Stream<Integer> stream = list.stream(); // 声明作为流处理
ParellerStream<Integer> pStream = stream.parallel(); // 转化为并行流
```

### 流操作

流处理的每个操作阶段都会封装到一个 Sink 接口里,处理数据后再将数据传递给下游的 Sink。

Stream操作分类
中间操作(Intermediate operations) 无状态(Stateless) unordered() filter() map() mapToInt() mapToLong() mapToDouble() flatMap() flatMapToInt() flatMapToLong() flatMapToDouble() peek()
有状态(Stateful) distinct() sorted() sorted() limit() skip()
结束操作(Terminal operations) 非短路操作 forEach() forEachOrdered() toArray() reduce() collect() max() min() count()
短路操作(short-circuiting) anyMatch() allMatch() noneMatch() findFirst() findAny()
Stream 上的所有操作分为两类:中间操作和结束操作。Stream 是延迟执行的,只有调用到结束操作,才触发整个流水线的执行。如果未定义结束操作,那么流处理什么也不会做。

Stream上的所有操作分为两类:中间操作和结束操作,中间操作只是一种标记,只有结束操作才会触发实际计算。中间操作又可以分为无状态的(Stateless)和有状态的(Stateful),无状态中间操作是指元素的处理不受前面元素的影响,而有状态的中间操作必须等到所有元素处理之后才知道最终结果,比如排序是有状态操作,在读取所有元素之前并不能确定排序结果;结束操作又可以分为短路操作和非短路操作,短路操作是指不用处理全部元素就可以返回结果,比如找到第一个满足条件的元素。之所以要进行如此精细的划分,是因为底层对每一种情况的处理方式不同。

实际上Stream API内部实现的的本质,就是如何重载Sink的这四个接口方法。(底层都是 sink 方法)
```java
// 获取空字符串的数量
int count = strings.parallelStream() // 声明作为流处理
.filter(string -> string.isEmpty()) // 中间操作,过滤空元素
.count(); // 结束操作,计数
```

---

## 中间操作

### 映射 map

Expand All @@ -68,31 +68,43 @@ List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(C

`filter` 方法用于通过设置的条件过滤出元素。

```java
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();
```

### 筛选 limit/skip


### 筛选 limit

`limit` 方法用于获取指定数量的流。
`limit` 方法用于获取指定数量的流(前 n 个), `skip` 方法用于去除指定数量的流(前 n 个)。

```java
// 筛选出 10 条数据
// 筛选出 11-20 条数据
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
random.ints().limit(20).skip(10).forEach(System.out::println);
```

### 排序 sorted

`sorted` 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
`sorted` 方法通过 Comparable 接口对流进行排序,也可以自定义。

```java
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
```

### 去重 distinct

`distinct` 方法通过流元素的 hashCode 和 equals 方法去除重复元素。

```java
Random random = new Random();
random.ints().distinct().forEach(System.out::println);
```

---

## 结束操作

### 迭代 forEach

Expand All @@ -104,6 +116,8 @@ Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
```

> 不要用 forEach 方法收集元素!stream 并行执行会损害正确性和效率,使用下方操作。
### 聚合 Collectors

结束操作:`Collectors` 类实现了归约操作,例如将流转换成集合和聚合元素,可用于返回列表或字符串。
Expand Down
21 changes: 14 additions & 7 deletions 其它/前端/css.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ div { letter-spacing:0.5em; } /* 简单选择器 */
- `position:absolute;` 设置元素为绝对定位
- `position:fixed;` 设置元素为固定定位


```css
/* 绝对定位到父元素左上角 */
.box {
position: absolute;
left: 10px; /* 同时设置 left 和 right 会强置元素宽度 */
top: 10px; /* 同时设置 top 和 bottom 会强置元素高度 */
}

```


> 子元素设置为 absolute 定位后,一般要把对应的父元素定位切换到 relative .

Expand Down Expand Up @@ -161,13 +173,8 @@ div { letter-spacing:0.5em; } /* 简单选择器 */
position: absolute;
top: 50%;
transform: translateY(-50%);
}

.child2 {
position: absolute;
left:50%;
top:50%;
transform: translate(-50%,-50%);
/* left:50%;
transform: translate(-50%,-50%); */
}
```

Expand Down
4 changes: 2 additions & 2 deletions 其它/前端/restful.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

- 获取:使用GET方法获取资源。
- 创建:使用POST创建新的资源。
- 更新:使用PUT更新现有资源。
- 删除:使用DELETE删除现有资源。
- 更新:使用PUT更新现有资源。(和 POST 近似)
- 删除:使用DELETE删除现有资源。(和 GET 近似)

```bash
[GET] /employees # 获取全部雇员信息
Expand Down
6 changes: 3 additions & 3 deletions 其它/前端/vue.md
Original file line number Diff line number Diff line change
Expand Up @@ -632,9 +632,9 @@ queryData('https://localhost:8080').then(function(data){
});
```
- p.then 获取异步正常执行结果
- p.catch 获取异常信息
- p.finally 无论正确与否都会触发
- `p.then` 获取异步正常执行结果
- `p.catch` 获取异常信息
- `p.finally` 无论正确与否都会触发
**请求嵌套**
Expand Down
Loading

0 comments on commit 3557340

Please sign in to comment.