Java各版本新增特性, Since Java 8

作者:Grey

原文地址:

Github

语雀

博客园

Java 8

Reactor of Java 这一章来自于《Spring in Action, 5th》 的笔记,因为这本书讲Reactor of Java讲的太好了,所以作为笔记摘抄了下来。

Reactor of Java

In an imperative programming model, the code would look something like this:

  1. String name = "Craig";
  2. String capitalName = name.toUpperCase();
  3. String greeting = "Hello, " + capitalName + "!";
  4. 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:

  1. Mono.just("Craig")
  2. .map(n -> n.toUpperCase())
  3. .map(n -> "Hello, " + n + " !")
  4. .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.

CREATING FROM OBJECTS

  1. Flux<String> fruitFlux = Flux
  2. .just("Apple", "Orange", "Grape", "Banana", "Strawberry");
  3. fruitFlux.subscribe(f -> System.out.println("Hello " + f));
  4. // for test
  5. StepVerifier.create(fruitFlux)
  6. .expectNext("Apple")
  7. .expectNext("Orange")
  8. .expectNext("Grape")
  9. .expectNext("Banana")
  10. .expectNext("Strawberry")
  11. .verifyComplete();

CREATING FROM COLLECTIONS

  1. Stream<String> fruitStream = Stream.of("Apple", "Orange", "Grape", "Banana", "Strawberry");
  2. Flux<String> fruitFlux2 = Flux.fromStream(fruitStream);
  3. fruitFlux2.subscribe(s -> System.out.println(s));
  4. List<String> fruitList = new ArrayList<>();
  5. fruitList.add("Apple");
  6. fruitList.add("Orange");
  7. fruitList.add("Grape");
  8. fruitList.add("Banana");
  9. fruitList.add("Strawberry");
  10. Flux<String> fruitFlux3 = Flux.fromIterable(fruitList);
  11. fruitFlux3.subscribe(s -> System.out.println(s));
  12. String[] fruits = new String[] {"Apple", "Orange", "Grape", "Banana", "Strawberry" };
  13. Flux<String> fruitFlux = Flux.fromArray(fruits);
  14. fruitFlux.subscribe(s -> System.out.println(s));
  15. StepVerifier.create(fruitFlux)
  16. .expectNext("Apple")
  17. .expectNext("Orange")
  18. .expectNext("Grape")
  19. .expectNext("Banana")
  20. .expectNext("Strawberry")
  21. .verifyComplete();

GENERATING FLUX DATA

  1. Flux<Integer> intervalFlux =
  2. Flux.range(1, 5);
  3. intervalFlux.subscribe(integer -> System.out.println(integer));
  4. StepVerifier.create(intervalFlux)
  5. .expectNext(1)
  6. .expectNext(2)
  7. .expectNext(3)
  8. .expectNext(4)
  9. .expectNext(5)
  10. .verifyComplete();
  11. Flux<Long> intervalFlux =
  12. Flux.interval(Duration.ofSeconds(1))
  13. .take(5);
  14. intervalFlux.subscribe(i -> System.out.println(i));
  15. StepVerifier.create(intervalFlux)
  16. .expectNext(0L)
  17. .expectNext(1L)
  18. .expectNext(2L)
  19. .expectNext(3L)
  20. .expectNext(4L)
  21. .verifyComplete();

MERGING REACTIVE TYPES

  1. Flux<String> characterFlux = Flux
  2. .just("Garfield", "Kojak", "Barbossa")
  3. .delayElements(Duration.ofMillis(500));
  4. Flux<String> foodFlux = Flux
  5. .just("Lasagna", "Lollipops", "Apples")
  6. .delaySubscription(Duration.ofMillis(250))
  7. .delayElements(Duration.ofMillis(500));
  8. Flux<String> mergedFlux = characterFlux.mergeWith(foodFlux);
  9. mergedFlux.subscribe(s -> System.out.println(s));
  10. StepVerifier.create(mergedFlux)
  11. .expectNext("Garfield")
  12. .expectNext("Lasagna")
  13. .expectNext("Kojak")
  14. .expectNext("Lollipops")
  15. .expectNext("Barbossa")
  16. .expectNext("Apples")
  17. .verifyComplete();
  18. Flux<String> characterFlux = Flux
  19. .just("Garfield", "Kojak", "Barbossa");
  20. Flux<String> foodFlux = Flux
  21. .just("Lasagna", "Lollipops", "Apples");
  22. Flux<Tuple2<String, String>> zippedFlux =
  23. Flux.zip(characterFlux, foodFlux);
  24. zippedFlux.subscribe(x -> System.out.println(x));
  25. StepVerifier.create(zippedFlux)
  26. .expectNextMatches(p ->
  27. p.getT1().equals("Garfield") &&
  28. p.getT2().equals("Lasagna"))
  29. .expectNextMatches(p ->
  30. p.getT1().equals("Kojak") &&
  31. p.getT2().equals("Lollipops"))
  32. .expectNextMatches(p ->
  33. p.getT1().equals("Barbossa") &&
  34. p.getT2().equals("Apples"))
  35. .verifyComplete();
  36. Flux<String> characterFlux = Flux
  37. .just("Garfield", "Kojak", "Barbossa");
  38. Flux<String> foodFlux = Flux
  39. .just("Lasagna", "Lollipops", "Apples");
  40. Flux<String> zippedFlux =
  41. Flux.zip(characterFlux, foodFlux, (c, f) -> c + " eats " + f);
  42. zippedFlux.subscribe(x -> System.out.println(x));
  43. StepVerifier.create(zippedFlux)
  44. .expectNext("Garfield eats Lasagna")
  45. .expectNext("Kojak eats Lollipops")
  46. .expectNext("Barbossa eats Apples")
  47. .verifyComplete();

SELECTING THE FIRST REACTIVE TYPE TO PUBLISH

  1. Flux<String> slowFlux = Flux.just("tortoise", "snail", "sloth")
  2. .delaySubscription(Duration.ofMillis(100));
  3. Flux<String> fastFlux = Flux.just("hare", "cheetah", "squirrel");
  4. Flux<String> firstFlux = Flux.first(slowFlux, fastFlux);
  5. StepVerifier.create(firstFlux)
  6. .expectNext("hare")
  7. .expectNext("cheetah")
  8. .expectNext("squirrel")
  9. .verifyComplete();

FILTERING DATA FROM REACTIVE TYPES

  1. Flux<String> skipFlux = Flux.just(
  2. "one", "two", "skip a few", "ninety nine", "one hundred")
  3. .skip(3);
  4. StepVerifier.create(skipFlux)
  5. .expectNext("ninety nine", "one hundred")
  6. .verifyComplete();
  7. Flux<String> skipFlux = Flux.just(
  8. "one", "two", "skip a few", "ninety nine", "one hundred")
  9. .delayElements(Duration.ofSeconds(1))
  10. .skip(Duration.ofSeconds(4));
  11. StepVerifier.create(skipFlux)
  12. .expectNext("ninety nine", "one hundred")
  13. .verifyComplete();
  14. Flux<String> nationalParkFlux = Flux.just(
  15. "Yellowstone", "Yosemite", "Grand Canyon",
  16. "Zion", "Grand Teton")
  17. .take(3);
  18. StepVerifier.create(nationalParkFlux)
  19. .expectNext("Yellowstone", "Yosemite", "Grand Canyon")
  20. .verifyComplete();
  21. Flux<String> nationalParkFlux = Flux.just(
  22. "Yellowstone", "Yosemite", "Grand Canyon",
  23. "Zion", "Grand Teton")
  24. .delayElements(Duration.ofSeconds(1))
  25. .take(Duration.ofMillis(3500));
  26. StepVerifier.create(nationalParkFlux)
  27. .expectNext("Yellowstone", "Yosemite", "Grand Canyon")
  28. .verifyComplete();
  29. Flux<String> nationalParkFlux = Flux.just(
  30. "Yellowstone", "Yosemite", "Grand Canyon",
  31. "Zion", "Grand Teton")
  32. .filter(np -> !np.contains(" "));
  33. StepVerifier.create(nationalParkFlux)
  34. .expectNext("Yellowstone", "Yosemite", "Zion")
  35. .verifyComplete();
  36. Flux<String> animalFlux = Flux.just(
  37. "dog", "cat", "bird", "dog", "bird", "anteater")
  38. .distinct();
  39. StepVerifier.create(animalFlux)
  40. .expectNext("dog", "cat", "bird", "anteater")
  41. .verifyComplete();

MAPPING REACTIVE DATA

  1. Flux<Player> playerFlux = Flux
  2. .just("Michael Jordan", "Scottie Pippen", "Steve Kerr")
  3. .map(n -> {
  4. String[] split = n.split("\\s");
  5. return new Player(split[0], split[1]);
  6. });
  7. StepVerifier.create(playerFlux)
  8. .expectNext(new Player("Michael", "Jordan"))
  9. .expectNext(new Player("Scottie", "Pippen"))
  10. .expectNext(new Player("Steve", "Kerr"))
  11. .verifyComplete();
  12. Flux<Player> playerFlux = Flux
  13. .just("Michael Jordan", "Scottie Pippen", "Steve Kerr")
  14. .flatMap(n -> Mono.just(n)
  15. .map(p -> {
  16. String[] split = p.split("\\s");
  17. return new Player(split[0], split[1]);
  18. })
  19. .subscribeOn(Schedulers.parallel())
  20. );
  21. List<Player> playerList = Arrays.asList(
  22. new Player("Michael", "Jordan"),
  23. new Player("Scottie", "Pippen"),
  24. new Player("Steve", "Kerr"));
  25. StepVerifier.create(playerFlux)
  26. .expectNextMatches(p -> playerList.contains(p))
  27. .expectNextMatches(p -> playerList.contains(p))
  28. .expectNextMatches(p -> playerList.contains(p))
  29. .verifyComplete();

BUFFERING DATA ON A REACTIVE STREAM

  1. Flux<String> fruitFlux = Flux.just(
  2. "apple", "orange", "banana", "kiwi", "strawberry");
  3. Flux<List<String>> bufferedFlux = fruitFlux.buffer(3);
  4. StepVerifier
  5. .create(bufferedFlux)
  6. .expectNext(Arrays.asList("apple", "orange", "banana"))
  7. .expectNext(Arrays.asList("kiwi", "strawberry"))
  8. .verifyComplete();
  9. 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:
  10. Flux.just(
  11. "apple", "orange", "banana", "kiwi", "strawberry")
  12. .buffer(3)
  13. .flatMap(x ->
  14. Flux.fromIterable(x)
  15. .map(y -> y.toUpperCase())
  16. .subscribeOn(Schedulers.parallel())
  17. .log()
  18. ).subscribe();
  19. Flux<String> fruitFlux = Flux.just(
  20. "apple", "orange", "banana", "kiwi", "strawberry");
  21. Mono<List<String>> fruitListMono = fruitFlux.collectList();
  22. StepVerifier
  23. .create(fruitListMono)
  24. .expectNext(Arrays.asList(
  25. "apple", "orange", "banana", "kiwi", "strawberry"))
  26. .verifyComplete();
  27. Flux<String> animalFlux = Flux.just(
  28. "aardvark", "elephant", "koala", "eagle", "kangaroo");
  29. Mono<Map<Character, String>> animalMapMono =
  30. animalFlux.collectMap(a -> a.charAt(0));
  31. StepVerifier
  32. .create(animalMapMono)
  33. .expectNextMatches(map -> {
  34. return
  35. map.size() == 3 &&
  36. map.get('a').equals("aardvark") &&
  37. map.get('e').equals("eagle") &&
  38. map.get('k').equals("kangaroo");
  39. })
  40. .verifyComplete();
  41. Performing logic operations on reactive types
  42. Flux<String> animalFlux = Flux.just(
  43. "aardvark", "elephant", "koala", "eagle", "kangaroo");
  44. Mono<Boolean> hasAMono = animalFlux.all(a -> a.contains("a"));
  45. StepVerifier.create(hasAMono)
  46. .expectNext(true)
  47. .verifyComplete();
  48. Mono<Boolean> hasKMono = animalFlux.all(a -> a.contains("k"));
  49. StepVerifier.create(hasKMono)
  50. .expectNext(false)
  51. .verifyComplete();
  52. Flux<String> animalFlux = Flux.just(
  53. "aardvark", "elephant", "koala", "eagle", "kangaroo");
  54. Mono<Boolean> hasAMono = animalFlux.any(a -> a.contains("a"));
  55. StepVerifier.create(hasAMono)
  56. .expectNext(true)
  57. .verifyComplete();
  58. Mono<Boolean> hasZMono = animalFlux.any(a -> a.contains("z"));
  59. StepVerifier.create(hasZMono)
  60. .expectNext(false)
  61. .verifyComplete();

Spring MVC change to Spring WebFlux

  1. @GetMapping("/recent")
  2. public Iterable<Taco> recentTacos() {
  3. PageRequest page = PageRequest.of(
  4. 0, 12, Sort.by("createdAt").descending());
  5. return tacoRepo.findAll(page).getContent();
  6. }
  7. @GetMapping("/recent")
  8. public Flux<Taco> recentTacos() {
  9. return Flux.fromIterable(tacoRepo.findAll()).take(12);
  10. }
  11. @PostMapping(consumes="application/json")
  12. @ResponseStatus(HttpStatus.CREATED)
  13. public Taco postTaco(@RequestBody Taco taco) {
  14. return tacoRepo.save(taco);
  15. }
  16. @PostMapping(consumes="application/json")
  17. @ResponseStatus(HttpStatus.CREATED)
  18. public Mono<Taco> postTaco(@RequestBody Mono<Taco> tacoMono) {
  19. return tacoRepo.saveAll(tacoMono).next();
  20. }
  21. public interface TacoRepository
  22. extends ReactiveCrudRepository<Taco, Long> {
  23. }
  24. @GetMapping("/{id}")
  25. public Taco tacoById(@PathVariable("id") Long id) {
  26. Optional<Taco> optTaco = tacoRepo.findById(id);
  27. if (optTaco.isPresent()) {
  28. return optTaco.get();
  29. }
  30. return null;
  31. }
  32. @GetMapping("/{id}")
  33. public Mono<Taco> tacoById(@PathVariable("id") Long id) {
  34. return tacoRepo.findById(id);
  35. }

WORKING WITH RXJAVA TYPES

  1. @GetMapping("/recent")
  2. public Observable<Taco> recentTacos() {
  3. return tacoService.getRecentTacos();
  4. }
  5. @GetMapping("/{id}")
  6. public Single<Taco> tacoById(@PathVariable("id") Long id) {
  7. return tacoService.lookupTaco(id);
  8. }

Developing Reactive APIs

  1. @Configuration
  2. public class RouterFunctionConfig {
  3. @Autowired
  4. private TacoRepository tacoRepo;
  5. @Bean
  6. public RouterFunction<?> routerFunction() {
  7. return route(GET("/design/taco"), this::recents)
  8. Testing reactive controllers 279
  9. .andRoute(POST("/design"), this::postTaco);
  10. }
  11. public Mono<ServerResponse> recents(ServerRequest request) {
  12. return ServerResponse.ok()
  13. .body(tacoRepo.findAll().take(12), Taco.class);
  14. }
  15. public Mono<ServerResponse> postTaco(ServerRequest request) {
  16. Mono<Taco> taco = request.bodyToMono(Taco.class);
  17. Mono<Taco> savedTaco = tacoRepo.save(taco);
  18. return ServerResponse
  19. .created(URI.create(
  20. "http://localhost:8080/design/taco/" +
  21. savedTaco.getId()))
  22. .body(savedTaco, Taco.class);
  23. }
  24. }

Test Reactive Rest APIs

  1. // Test Get Method
  2. Taco[] tacos = {
  3. testTaco(1L), testTaco(2L),
  4. testTaco(3L), testTaco(4L),
  5. testTaco(5L), testTaco(6L),
  6. testTaco(7L), testTaco(8L),
  7. testTaco(9L), testTaco(10L),
  8. testTaco(11L), testTaco(12L),
  9. testTaco(13L), testTaco(14L),
  10. testTaco(15L), testTaco(16L)};
  11. Flux<Taco> tacoFlux = Flux.just(tacos);
  12. TacoRepository tacoRepo = Mockito.mock(TacoRepository.class);
  13. when(tacoRepo.findAll()).thenReturn(tacoFlux);
  14. WebTestClient testClient = WebTestClient.bindToController(
  15. new DesignTacoController(tacoRepo))
  16. .build();
  17. testClient.get().uri("/design/recent")
  18. .exchange()
  19. .expectStatus().isOk()
  20. .expectBody()
  21. .jsonPath("$").isArray()
  22. .jsonPath("$").isNotEmpty()
  23. .jsonPath("$[0].id").isEqualTo(tacos[0].getId().toString())
  24. .jsonPath("$[0].name").isEqualTo("Taco 1").jsonPath("$[1].id")
  25. .isEqualTo(tacos[1].getId().toString()).jsonPath("$[1].name")
  26. .isEqualTo("Taco 2").jsonPath("$[11].id")
  27. .isEqualTo(tacos[11].getId().toString())
  28. .jsonPath("$[11].name").isEqualTo("Taco 12").jsonPath("$[12]")
  29. .doesNotExist().jsonPath("$[12]").doesNotExist();
  30. // Test POST Method
  31. TacoRepository tacoRepo = Mockito.mock(
  32. TacoRepository.class);
  33. Mono<Taco> unsavedTacoMono = Mono.just(testTaco(null));
  34. Taco savedTaco = testTaco(null);
  35. savedTaco.setId(1L);
  36. Mono<Taco> savedTacoMono = Mono.just(savedTaco);
  37. when(tacoRepo.save(any())).thenReturn(savedTacoMono);
  38. WebTestClient testClient = WebTestClient.bindToController(
  39. new DesignTacoController(tacoRepo)).build();
  40. testClient.post()
  41. .uri("/design")
  42. .contentType(MediaType.APPLICATION_JSON)
  43. .body(unsavedTacoMono, Taco.class)
  44. .exchange()
  45. .expectStatus().isCreated()
  46. .expectBody(Taco.class)
  47. .isEqualTo(savedTaco);
  48. // Testing with a live server
  49. @RunWith(SpringRunner.class)
  50. @SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
  51. public class DesignTacoControllerWebTest {
  52. @Autowired
  53. private WebTestClient testClient;
  54. @Test
  55. public void shouldReturnRecentTacos() throws IOException {
  56. testClient.get().uri("/design/recent")
  57. .accept(MediaType.APPLICATION_JSON).exchange()
  58. .expectStatus().isOk()
  59. .expectBody()
  60. .jsonPath("$[?(@.id == 'TACO1')].name")
  61. .isEqualTo("Carnivore")
  62. .jsonPath("$[?(@.id == 'TACO2')].name")
  63. .isEqualTo("Bovine Bounty")
  64. .jsonPath("$[?(@.id == 'TACO3')].name")
  65. .isEqualTo("Veg-Out");
  66. }
  67. }

Consume Reactive APIs

  1. Flux ingredients = WebClient.create()
  2. .get()
  3. .uri("http://localhost:8080/ingredients")
  4. .retrieve()
  5. .bodyToFlux(Ingredient.class);
  6. ingredients.subscribe(i -> { ...})
  7. Flux<Ingredient> ingredients = WebClient.create()
  8. .get()
  9. .uri("http://localhost:8080/ingredients")
  10. .retrieve()
  11. .bodyToFlux(Ingredient.class);
  12. ingredients
  13. .timeout(Duration.ofSeconds(1))
  14. .subscribe(
  15. i -> { ... },
  16. e -> {
  17. // handle timeout error
  18. })
  19. //Handing errors
  20. ingredientMono.subscribe(
  21. ingredient -> {
  22. // handle the ingredient data
  23. ...
  24. },
  25. error-> {
  26. // deal with the error
  27. ...
  28. });
  29. Mono<Ingredient> ingredientMono = webClient
  30. .get()
  31. .uri("http://localhost:8080/ingredients/{id}", ingredientId)
  32. .retrieve()
  33. .onStatus(HttpStatus::is4xxClientError,
  34. response -> Mono.just(new UnknownIngredientException()))
  35. .bodyToMono(Ingredient.class);

Java 9

jshell

无法用单个下划线作为变量名称

  1. int _ = 3; // java9 or above , error
  1. String a = Objects.requireNonNullElse(m,"Bc"); // 若m不为null,则a = m,若m为null,则a = "Bc"
  1. -cp, -classpath, --class-path(Java9新增)

Multi-Release JAR Files

  1. --release
  2. --class-path instead of -classpath
  3. --version instead of -version
  4. --module-path option has a shortcut -p

更多,见jeps

Java8中,接口可以有静态方法的默认实现,例:

  1. public interface Test {
  2. public static void print() {
  3. System.out.println("interface print");
  4. }
  5. default void pout() {
  6. System.out.println();
  7. }
  8. }

Java9中,可以支持private的静态方法实现。

  1. public interface Test {
  2. private static void print() {
  3. System.out.println("interface print");
  4. }
  5. static void pout() {
  6. print();
  7. }
  8. }
  1. Optional.ofNullable(date).orElseGet(() -> newDate()); // date为null,才会执行newDate()方法,否则不执行newDate()方法
  2. Optional.ofNullable(date).orElse(newDate()); // 无论date是否为null,都会执行newDate()方法

Java7中,可以使用try-with-Resources

  1. try(Resouce res = ...) {
  2. work with res
  3. }

res.close()会被自动执行

例:

  1. try (var in = new Scanner(new FileInputStream("C:\\Users\\Young\\Desktop\\新建文件夹\\1.tx.txt"), StandardCharsets.UTF_8);
  2. var out = new PrintWriter("C:\\Users\\Young\\Desktop\\新建文件夹\\out.txt", StandardCharsets.UTF_8)) {
  3. while (in.hasNext()) {
  4. out.println(in.next().toUpperCase());
  5. }
  6. }

in 和 out执行完毕后都会自动关闭资源

在Java9 中,你可以在try中预先声明资源

例:

  1. public static void printAll(String[] lines, PrintWriter out) {
  2. try (out) { // effectively final variable
  3. for (String line : lines) {
  4. out.println(line);
  5. } // out.close() called here
  6. }
  7. }

StackWalker用法示例

  1. public class App {
  2. /**
  3. * Computes the factorial of a number
  4. *
  5. * @param n a non-negative integer
  6. * @return n! = 1 * 2 * . . . * n
  7. */
  8. public static int factorial(int n) {
  9. System.out.println("factorial(" + n + "):");
  10. var walker = StackWalker.getInstance();
  11. walker.forEach(System.out::println);
  12. int r;
  13. if (n <= 1) {
  14. r = 1;
  15. } else {
  16. r = n * factorial(n - 1);
  17. }
  18. System.out.println("return " + r);
  19. return r;
  20. }
  21. public static void main(String[] args) {
  22. try (var in = new Scanner(System.in)) {
  23. System.out.print("Enter n: ");
  24. int n = in.nextInt();
  25. factorial(n);
  26. }
  27. }
  28. }

Java 9 expands the use of the diamond syntax to situations where it was previously not accepted. For example , you can now use diamonds with anonymous subclasses.

  1. ArrayList<String> list = new ArrayList<>(){
  2. @Override
  3. public String get(int index) {
  4. return super.get(index).replaceAll(".","*");
  5. }
  6. };

Java 10

无需定义变量类型,通过var关键字+初始化的值,可以推测出变量类型

  1. var a = 2; // a表示int
  2. var b = "hello"; // b 表示String
  3. var date = new java.util.Date();
  4. var obj = new Custome(); // 自定义对象

Java 11

  1. String repeated = "Java".repeat(3); // 三个Java字符串连接

JDK提供了jdeprscan 来检查你的代码是否使用了deprecated的方法

专题

Lambda Expression

Method Reference Equivalent Lambda Expression Notes
separator::equals x -> separator.equals(x) This is a method expression with an object and an instance method. The lambda parameter is passed as the explicit parameter of the method
String::trim x -> x.trim() This is a method expression with a class and an instance method. The lambda parameter becomes the explicit parameter of the method
String::concat (x, y) -> x.concat(y) Again, we have an instance method, but this time, with an explicit parameter. As before, the first lambda parameter becomes the implicit parameter, and the remaining ones are passed to the method
Integer::valueOf x -> Integer::valueOf(x) This is a method expression with a static method. The lambda parameter is passed to the static method
Integer::sum (x, y) -> Integer::sum(x, y) This is another static method, but this time with two parameters. Both lambda parameters are passed to the static method. The Integer.sum method was specifically created to be used as a method reference. As a lmbda, you could just write (x, y)->x + y
Integer::new x -> new Integer(x) This is a constructor reference. The lambda parameters are passed to the constructor
Integer[]::new n -> new Integer[n] This is an array constructor reference. The lambda paramter is the array length
Functional Interface Parameter Types Return Types Abstract Method Name Description Other Method
Runnable none void run Runs an action without arguments or return value
Supplier none T get Supplies a value of type T
Consumer T void accept Consumes a value of type T andThen
BiConsumer<T,U> T,U void accept Consumes  value of types T and U andThen
Function<T,R> T R apply A function with argument of type T compose, andThen, identity
BiFunction<T,U,R> T,U R apply A function with arguments of types T and U andThen
UnaryOperator T T apply A unary operator on the type T compose, andThen, identity
BinaryOperator T,T T apply A binary operator on the type T andThen, maxBy, minBy
Predicate T boolean test A boolean-valued function and, or, negate, isEqual
BiPredicate<T,U> T,U boolean test A boolean-valued function with two argumnets and,or,negate

Functional interfaces for Primitive Types

p, q is int ,long double; P, Q is Int, Long, Double

Functional Interface Parameter Types Return Types Abstract Method Name
BooleanSupplier none boolean getAsBoolean
PSupplier none p getAsP
PConsumer p void accept
ObjPConsumer T,p void accept
PFunction p T apply
PToQFunction p q applyAsQ
ToPFunction T p applyAsP
ToPBiFunction<T,U> T,U p applyAsP
PUnaryOperator p p applyAsP
PBinaryOperator p,p p applyAsP
PPredicate p boolean test

Service Loaders

Proxies

Logging

Generic Programming

  • E for the element type of a collection
  • K and V for key and value type of a table
  • T(and the neighboring letters U and S, if neccessary) for "any type at all"
  1. Pair<String> a = new Pair<>("A", "B");
  2. Pair<Double> b = new Pair<>(1.1, 1.11);
  3. System.out.println(a.getClass() == b.getClass()); // TRUE

in Java8

  1. public static <T> Pair<T> makePair(Supplier<T> constr) {
  2. return new Pair<>(constr.get(), constr.get());
  3. }
  4. Pair<String> p = Pair.makePair(String:new);

In general, there is no relationship between Pair<S> and Pair<T>, no matter how S and T are related.

BUT

  1. var managerBuiddies = new Pair<Manager>(ceo, cfo);
  2. Pair<? extends Employee> buddies = managerBuddies;

Collections

Concurrency

Stream

Java 8

  1. // 流操作
  2. List<Integer> list = new ArrayList<>();
  3. list.add(1);
  4. list.add(2);
  5. list.parallelStream().filter(i -> i > 1).count();
  6. list.stream().filter(i -> i > 1).count();
  7. Stream<String> words = Stream.of(contents.split(","));
  8. // 创建流
  9. var limits = new BigInteger("1000");
  10. Stream<BigInteger> integerStream = Stream.iterate(BigInteger.ZERO, n -> n.compareTo(limits) < 0, n -> n.add(BigInteger.ONE));
  11. System.out.println(integerStream.count());

如果我们持有的iterable对象不是集合,那么可以通过下面的调用将其转换成一个流

  1. StreamSupport.stream(iterable.spliterator(),false);

如果我们持有的是Iterator对象,并且希望得到一个由它的结果构成的流,那么可以使用下面的语句

  1. StreamSupport.stream(Spliterators.spliteratorUnknowSize(iterator, Spliterator.ORDERED),false);

至关重要的是,在执行流的操作时,我们并没有修改流背后的集合。记住,流并没有收集其数据,数据一直存储在单独的集合中

Optional

  1. String result = optionalString.orElse(""); // The wrapped string , or "" if none
  2. String result = optionalString.orElseGet(() -> System.getProperty("myapp.default"));
  3. String result = optionalString.orElseThrow(IllegalStateException::new);

消费Optinal值

  1. optionalValue.ifPresent(v -> result.add(v));
  2. optionalValue.ifPresentOrElse(v -> System.out.println("Found" + v),
  3. ()-> logger.warning("no match"));

管道化Optional

  1. Optional<String> transformed = optionalString.filter(s -> s.length() >= 8).map(String::toUpperCase);

in Java9

  1. // 如果optionalString的值存在,那么result为optionalString,如果值不存在,那么就会计算lambda表达式,并使用计算出来的结果
  2. Optional<String> transformed = optionalString.or(() -> alternatives.stream().findFirst());

参考资料

Spring in Action, 5th

Java核心技术·卷 I(原书第11版)

Java核心技术·卷 II(原书第11版)

Java各版本新增特性, Since Java 8的更多相关文章

  1. Java SE 8 新增特性

    Java SE 8 新增特性 作者:Grey 原文地址: Java SE 8 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new_ ...

  2. Java SE 10 新增特性

    Java SE 10 新增特性 作者:Grey 原文地址:Java SE 10 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  3. Java SE 11 新增特性

    Java SE 11 新增特性 作者:Grey 原文地址:Java SE 11 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  4. Java SE 12 新增特性

    Java SE 12 新增特性 作者:Grey 原文地址:Java SE 12 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  5. Java SE 19 新增特性

    Java SE 19 新增特性 作者:Grey 原文地址: 博客园:Java SE 19 新增特性 CSDN:Java SE 19 新增特性 源码 源仓库: Github:java_new_featu ...

  6. Java SE 9 新增特性

    Java SE 9 新增特性 作者:Grey 原文地址: Java SE 9 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new_ ...

  7. Java SE 13 新增特性

    Java SE 13 新增特性 作者:Grey 原文地址:Java SE 13 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  8. Java SE 14 新增特性

    Java SE 14 新增特性 作者:Grey 原文地址:Java SE 14 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

  9. Java SE 15 新增特性

    Java SE 15 新增特性 作者:Grey 原文地址:Java SE 15 新增特性 源码 源仓库: Github:java_new_features 镜像仓库: GitCode:java_new ...

随机推荐

  1. python-基础入门-2

    这里介绍两个,相当于c中的scanf函数 第一个raw_input 1 age=raw_input("how old are you ") 2 print "you ar ...

  2. 如何能够将MathType工具栏放大?

    作为专业的公式编辑器,MathType受到了很多用户的青睐,因为借助它可以快速编写出想要的各种数学公式.但是有的用户发现MathType工具栏中的符号有一些小,那么为了方便使用,能不能将工具栏放大呢? ...

  3. kafka对接Rancher日志

    kafka对接Rancher日志 目录 kafka对接Rancher日志 概述 环境准备 正常对接kafka集群 1.helm添加bitnami库 2.下载 kafka 对应的chart压缩文件 3. ...

  4. python接口测试3-JSON格式

    什么是JSON? 一种轻量级的数据交换格式.它独立于语言和平台,JSON解析器和JSON库支持不同的编程语言.JSON具有自我描述性,很容易理解. 数据格式: { "name":& ...

  5. appium服务器参数

    appium服务器初始化参数 Appium服务器初始化参数(功能) 设置能力 能力参数项 获取appPackage与appActivity 查看当前活动名称 使用uiautomatorviewer定位 ...

  6. PowerManagerService流程分析

    一.PowerManagerService简介 PowerManagerService主要服务Android系统电源管理工作,这样讲比较笼统,就具体细节上大致可以认为PowerManagerServi ...

  7. 现代富文本编辑器Quill的模块化机制

    DevUI是一支兼具设计视角和工程视角的团队,服务于华为云DevCloud平台和华为内部数个中后台系统,服务于设计师和前端工程师.官方网站:devui.designNg组件库:ng-devui(欢迎S ...

  8. CenOS下监控工具尝试

    Cacti cacti重图形,有数据历史,需要用到数据库支持,支持web配置,默认不支持告警,可以加插件. Server端配置 安装epel yum install -y epel-release 安 ...

  9. MOS管基础知识

    一些关于MOS管的基础知识,很多资料来源于网络. 场效应管(FET)分类:(按材料) 1. 结型 2. 绝缘栅型(MOS) 耗尽型:在SiO2绝缘层中掺入了大量的碱金属正离子Na+或K+(制造P沟道耗 ...

  10. java46

    1.迭代器遍历 import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public c ...