Java各版本新增特性, Since Java 8
阿新 • • 發佈:2020-12-16
# Java各版本新增特性, Since Java 8
作者:[Grey](https://www.cnblogs.com/greyzeng/)
原文地址:
[Github](https://github.com/GreyZeng/articles/blob/master/Java%E5%90%84%E7%89%88%E6%9C%AC%E6%96%B0%E5%A2%9E%E7%89%B9%E6%80%A7.md)
[語雀](https://www.yuque.com/greyzeng/uzfhep/qefgos)
[部落格園](https://www.cnblogs.com/greyzeng/p/14139032.html)
## Java 8
> Reactor of Java 這一章來自於[《Spring in Action, 5th》](https://book.douban.com/subject/30346440/) 的筆記,因為這本書講Reactor of Java講的太好了,所以作為筆記摘抄了下來。
### Reactor of Java
In an imperative programming model, the code would look something like this:
```java
String name = "Craig";
String capitalName = name.toUpperCase();
String greeting = "Hello, " + capitalName + "!";
System.out.println(greeting);
```
In the imperative model, each line of code performs a step, one right after the other, and definitely in the same thread. Each step blocks the executing thread from moving to the next step until complete. In contrast, functional, reactive code could achieve the same thing like this:
```java
Mono.just("Craig")
.map(n -> n.toUpperCase())
.map(n -> "Hello, " + n + " !")
.subscribe(System.out::println);
```
The Mono in the example is one of Reactor’s two core types. Flux is the other. Both are implementations of Reactive Streams’ Publisher.
A Flux represents** a pipeline of zero, one, or many (potentially infinite) data items**.
A Mono is a specialized reactive type that’s optimized for when the dataset is known to have **no more than one data** item.
![](https://cdn.nlark.com/yuque/0/2020/png/757806/1583580980687-10d3732c-fc88-4626-be52-7f9c98fe10a4.png#align=left&display=inline&height=687&originHeight=687&originWidth=1198&status=done&style=none&width=1198)
![](https://cdn.nlark.com/yuque/0/2020/png/757806/1583580980714-8e157176-3a2f-4b80-9d56-79d091525980.png#align=left&display=inline&height=683&originHeight=683&originWidth=1281&status=done&style=none&width=1281)
CREATING FROM OBJECTS
```java
Flux fruitFlux = Flux
.just("Apple", "Orange", "Grape", "Banana", "Strawberry");
fruitFlux.subscribe(f -> System.out.println("Hello " + f));
// for test
StepVerifier.create(fruitFlux)
.expectNext("Apple")
.expectNext("Orange")
.expectNext("Grape")
.expectNext("Banana")
.expectNext("Strawberry")
.verifyComplete();
```
CREATING FROM COLLECTIONS
```java
Stream fruitStream = Stream.of("Apple", "Orange", "Grape", "Banana", "Strawberry");
Flux fruitFlux2 = Flux.fromStream(fruitStream);
fruitFlux2.subscribe(s -> System.out.println(s));
List fruitList = new ArrayList<>();
fruitList.add("Apple");
fruitList.add("Orange");
fruitList.add("Grape");
fruitList.add("Banana");
fruitList.add("Strawberry");
Flux fruitFlux3 = Flux.fromIterable(fruitList);
fruitFlux3.subscribe(s -> System.out.println(s));
String[] fruits = new String[] {"Apple", "Orange", "Grape", "Banana", "Strawberry" };
Flux fruitFlux = Flux.fromArray(fruits);
fruitFlux.subscribe(s -> System.out.println(s));
StepVerifier.create(fruitFlux)
.expectNext("Apple")
.expectNext("Orange")
.expectNext("Grape")
.expectNext("Banana")
.expectNext("Strawberry")
.verifyComplete();
```
GENERATING FLUX DATA
```java
Flux intervalFlux =
Flux.range(1, 5);
intervalFlux.subscribe(integer -> System.out.println(integer));
StepVerifier.create(intervalFlux)
.expectNext(1)
.expectNext(2)
.expectNext(3)
.expectNext(4)
.expectNext(5)
.verifyComplete();
Flux intervalFlux =
Flux.interval(Duration.ofSeconds(1))
.take(5);
intervalFlux.subscribe(i -> System.out.println(i));
StepVerifier.create(intervalFlux)
.expectNext(0L)
.expectNext(1L)
.expectNext(2L)
.expectNext(3L)
.expectNext(4L)
.verifyComplete();
```
MERGING REACTIVE TYPES
```java
Flux characterFlux = Flux
.just("Garfield", "Kojak", "Barbossa")
.delayElements(Duration.ofMillis(500));
Flux foodFlux = Flux
.just("Lasagna", "Lollipops", "Apples")
.delaySubscription(Duration.ofMillis(250))
.delayElements(Duration.ofMillis(500));
Flux mergedFlux = characterFlux.mergeWith(foodFlux);
mergedFlux.subscribe(s -> System.out.println(s));
StepVerifier.create(mergedFlux)
.expectNext("Garfield")
.expectNext("Lasagna")
.expectNext("Kojak")
.expectNext("Lollipops")
.expectNext("Barbossa")
.expectNext("Apples")
.verifyComplete();
Flux characterFlux = Flux
.just("Garfield", "Kojak", "Barbossa");
Flux foodFlux = Flux
.just("Lasagna", "Lollipops", "Apples");
Flux> zippedFlux =
Flux.zip(characterFlux, foodFlux);
zippedFlux.subscribe(x -> System.out.println(x));
StepVerifier.create(zippedFlux)
.expectNextMatches(p ->
p.getT1().equals("Garfield") &&
p.getT2().equals("Lasagna"))
.expectNextMatches(p ->
p.getT1().equals("Kojak") &&
p.getT2().equals("Lollipops"))
.expectNextMatches(p ->
p.getT1().equals("Barbossa") &&
p.getT2().equals("Apples"))
.verifyComplete();
Flux characterFlux = Flux
.just("Garfield", "Kojak", "Barbossa");
Flux foodFlux = Flux
.just("Lasagna", "Lollipops", "Apples");
Flux zippedFlux =
Flux.zip(characterFlux, foodFlux, (c, f) -> c + " eats " + f);
zippedFlux.subscribe(x -> System.out.println(x));
StepVerifier.create(zippedFlux)
.expectNext("Garfield eats Lasagna")
.expectNext("Kojak eats Lollipops")
.expectNext("Barbossa eats Apples")
.verifyComplete();
```
SELECTING THE FIRST REACTIVE TYPE TO PUBLISH
```java
Flux slowFlux = Flux.just("tortoise", "snail", "sloth")
.delaySubscription(Duration.ofMillis(100));
Flux fastFlux = Flux.just("hare", "cheetah", "squirrel");
Flux firstFlux = Flux.first(slowFlux, fastFlux);
StepVerifier.create(firstFlux)
.expectNext("hare")
.expectNext("cheetah")
.expectNext("squirrel")
.verifyComplete();
```
FILTERING DATA FROM REACTIVE TYPES
```java
Flux skipFlux = Flux.just(
"one", "two", "skip a few", "ninety nine", "one hundred")
.skip(3);
StepVerifier.create(skipFlux)
.expectNext("ninety nine", "one hundred")
.verifyComplete();
Flux skipFlux = Flux.just(
"one", "two", "skip a few", "ninety nine", "one hundred")
.delayElements(Duration.ofSeconds(1))
.skip(Duration.ofSeconds(4));
StepVerifier.create(skipFlux)
.expectNext("ninety nine", "one hundred")
.verifyComplete();
Flux nationalParkFlux = Flux.just(
"Yellowstone", "Yosemite", "Grand Canyon",
"Zion", "Grand Teton")
.take(3);
StepVerifier.create(nationalParkFlux)
.expectNext("Yellowstone", "Yosemite", "Grand Canyon")
.verifyComplete();
Flux nationalParkFlux = Flux.just(
"Yellowstone", "Yosemite", "Grand Canyon",
"Zion", "Grand Teton")
.delayElements(Duration.ofSeconds(1))
.take(Duration.ofMillis(3500));
StepVerifier.create(nationalParkFlux)
.expectNext("Yellowstone", "Yosemite", "Grand Canyon")
.verifyComplete();
Flux nationalParkFlux = Flux.just(
"Yellowstone", "Yosemite", "Grand Canyon",
"Zion", "Grand Teton")
.filter(np -> !np.contains(" "));
StepVerifier.create(nationalParkFlux)
.expectNext("Yellowstone", "Yosemite", "Zion")
.verifyComplete();
Flux animalFlux = Flux.just(
"dog", "cat", "bird", "dog", "bird", "anteater")
.distinct();
StepVerifier.create(animalFlux)
.expectNext("dog", "cat", "bird", "anteater")
.verifyComplete();
```
MAPPING REACTIVE DATA
```java
Flux playerFlux = Flux
.just("Michael Jordan", "Scottie Pippen", "Steve Kerr")
.map(n -> {
String[] split = n.split("\\s");
return new Player(split[0], split[1]);
});
StepVerifier.create(playerFlux)
.expectNext(new Player("Michael", "Jordan"))
.expectNext(new Player("Scottie", "Pippen"))
.expectNext(new Player("Steve", "Kerr"))
.verifyComplete();
Flux playerFlux = Flux
.just("Michael Jordan", "Scottie Pippen", "Steve Kerr")
.flatMap(n -> Mono.just(n)
.map(p -> {
String[] split = p.split("\\s");
return new Player(split[0], split[1]);
})
.subscribeOn(Schedulers.parallel())
);
List playerList = Arrays.asList(
new Player("Michael", "Jordan"),
new Player("Scottie", "Pippen"),
new Player("Steve", "Kerr"));
StepVerifier.create(playerFlux)
.expectNextMatches(p -> playerList.contains(p))
.expectNextMatches(p -> playerList.contains(p))
.expectNextMatches(p -> playerList.contains(p))
.verifyComplete();
```
BUFFERING DATA ON A REACTIVE STREAM
```java
Flux fruitFlux = Flux.just(
"apple", "orange", "banana", "kiwi", "strawberry");
Flux
- > bufferedFlux = fruitFlux.buffer(3);
StepVerifier
.create(bufferedFlux)
.expectNext(Arrays.asList("apple", "orange", "banana"))
.expectNext(Arrays.asList("kiwi", "strawberry"))
.verifyComplete();
Buffering values from a reactive Flux into non-reactive List collections seems counterproductive. But when you combine buffer() with flatMap(), it enables each of the List collections to be processed in parallel:
Flux.just(
"apple", "orange", "banana", "kiwi", "strawberry")
.buffer(3)
.flatMap(x ->
Flux.fromIterable(x)
.map(y -> y.toUpperCase())
.subscribeOn(Schedulers.parallel())
.log()
).subscribe();
Flux
- > fruitListMono = fruitFlux.collectList();
StepVerifier
.create(fruitListMono)
.expectNext(Arrays.asList(
"apple", "orange", "banana", "kiwi", "strawberry"))
.verifyComplete();
Flux