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

2024-04-10 12:38
文章标签 java 特性 新增 版本 since

本文主要是介绍Java各版本新增特性, Since Java 8,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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:

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:

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.

CREATING FROM OBJECTS

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

Stream fruitStream = Stream.of(“Apple”, “Orange”, “Grape”, “Banana”, “Strawberry”);
Flux fruitFlux2 = Flux.fromStream(fruitStream);
fruitFlux2.subscribe(s -> System.out.println(s));

    List<String> fruitList = new ArrayList<>();fruitList.add("Apple");fruitList.add("Orange");fruitList.add("Grape");fruitList.add("Banana");fruitList.add("Strawberry");Flux<String> fruitFlux3 = Flux.fromIterable(fruitList);fruitFlux3.subscribe(s -> System.out.println(s));String[] fruits = new String[] {"Apple", "Orange", "Grape", "Banana", "Strawberry" };Flux<String> 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

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

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<Tuple2<String, String>> 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

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

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

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§)
.expectNextMatches(p -> playerList.contains§)
.expectNextMatches(p -> playerList.contains§)
.verifyComplete();
BUFFERING DATA ON A REACTIVE STREAM

Flux fruitFlux = Flux.just(
“apple”, “orange”, “banana”, “kiwi”, “strawberry”);

Flux<List> 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 fruitFlux = Flux.just(
“apple”, “orange”, “banana”, “kiwi”, “strawberry”);

Mono<List> fruitListMono = fruitFlux.collectList();

StepVerifier
.create(fruitListMono)
.expectNext(Arrays.asList(
“apple”, “orange”, “banana”, “kiwi”, “strawberry”))
.verifyComplete();

Flux animalFlux = Flux.just(
“aardvark”, “elephant”, “koala”, “eagle”, “kangaroo”);

Mono<Map<Character, String>> animalMapMono =
animalFlux.collectMap(a -> a.charAt(0));

StepVerifier
.create(animalMapMono)
.expectNextMatches(map -> {
return
map.size() == 3 &&
map.get(‘a’).equals(“aardvark”) &&
map.get(‘e’).equals(“eagle”) &&
map.get(‘k’).equals(“kangaroo”);
})
.verifyComplete();

Performing logic operations on reactive types
Flux animalFlux = Flux.just(
“aardvark”, “elephant”, “koala”, “eagle”, “kangaroo”);

Mono hasAMono = animalFlux.all(a -> a.contains(“a”));
StepVerifier.create(hasAMono)
.expectNext(true)
.verifyComplete();

Mono hasKMono = animalFlux.all(a -> a.contains(“k”));
StepVerifier.create(hasKMono)
.expectNext(false)
.verifyComplete();

Flux animalFlux = Flux.just(
“aardvark”, “elephant”, “koala”, “eagle”, “kangaroo”);

Mono hasAMono = animalFlux.any(a -> a.contains(“a”));

StepVerifier.create(hasAMono)
.expectNext(true)
.verifyComplete();

Mono hasZMono = animalFlux.any(a -> a.contains(“z”));
StepVerifier.create(hasZMono)
.expectNext(false)
.verifyComplete();
Spring MVC change to Spring WebFlux

@GetMapping("/recent")
public Iterable recentTacos() {
PageRequest page = PageRequest.of(
0, 12, Sort.by(“createdAt”).descending());
return tacoRepo.findAll(page).getContent();
}

@GetMapping("/recent")
public Flux recentTacos() {
return Flux.fromIterable(tacoRepo.findAll()).take(12);
}

@PostMapping(consumes=“application/json”)
@ResponseStatus(HttpStatus.CREATED)
public Taco postTaco(@RequestBody Taco taco) {
return tacoRepo.save(taco);
}
@PostMapping(consumes=“application/json”)
@ResponseStatus(HttpStatus.CREATED)
public Mono postTaco(@RequestBody Mono tacoMono) {
return tacoRepo.saveAll(tacoMono).next();
}

public interface TacoRepository
extends ReactiveCrudRepository<Taco, Long> {
}
@GetMapping("/{id}")
public Taco tacoById(@PathVariable(“id”) Long id) {
Optional optTaco = tacoRepo.findById(id);
if (optTaco.isPresent()) {
return optTaco.get();
}
return null;
}
@GetMapping("/{id}")
public Mono tacoById(@PathVariable(“id”) Long id) {
return tacoRepo.findById(id);
}
WORKING WITH RXJAVA TYPES

@GetMapping("/recent")
public Observable recentTacos() {
return tacoService.getRecentTacos();
}

@GetMapping("/{id}")
public Single tacoById(@PathVariable(“id”) Long id) {
return tacoService.lookupTaco(id);
}
Developing Reactive APIs

@Configuration
public class RouterFunctionConfig {
@Autowired
private TacoRepository tacoRepo;
@Bean
public RouterFunction<?> routerFunction() {
return route(GET("/design/taco"), this::recents)
Testing reactive controllers 279
.andRoute(POST("/design"), this::postTaco);
}
public Mono recents(ServerRequest request) {
return ServerResponse.ok()
.body(tacoRepo.findAll().take(12), Taco.class);
}
public Mono postTaco(ServerRequest request) {
Mono taco = request.bodyToMono(Taco.class);
Mono savedTaco = tacoRepo.save(taco);
return ServerResponse
.created(URI.create(
“http://localhost:8080/design/taco/” +
savedTaco.getId()))
.body(savedTaco, Taco.class);
}
}
Test Reactive Rest APIs

// Test Get Method
Taco[] tacos = {
testTaco(1L), testTaco(2L),
testTaco(3L), testTaco(4L),
testTaco(5L), testTaco(6L),
testTaco(7L), testTaco(8L),
testTaco(9L), testTaco(10L),
testTaco(11L), testTaco(12L),
testTaco(13L), testTaco(14L),
testTaco(15L), testTaco(16L)};
Flux tacoFlux = Flux.just(tacos);
TacoRepository tacoRepo = Mockito.mock(TacoRepository.class);
when(tacoRepo.findAll()).thenReturn(tacoFlux);
WebTestClient testClient = WebTestClient.bindToController(
new DesignTacoController(tacoRepo))
.build();
testClient.get().uri("/design/recent")
.exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath(" " ) . i s A r r a y ( ) . j s o n P a t h ( " ").isArray() .jsonPath(" ").isArray().jsonPath("").isNotEmpty()
.jsonPath(" [ 0 ] . i d " ) . i s E q u a l T o ( t a c o s [ 0 ] . g e t I d ( ) . t o S t r i n g ( ) ) . j s o n P a t h ( " [0].id").isEqualTo(tacos[0].getId().toString()) .jsonPath(" [0].id").isEqualTo(tacos[0].getId().toString()).jsonPath("[0].name").isEqualTo(“Taco 1”).jsonPath(" [ 1 ] . i d " ) . i s E q u a l T o ( t a c o s [ 1 ] . g e t I d ( ) . t o S t r i n g ( ) ) . j s o n P a t h ( " [1].id") .isEqualTo(tacos[1].getId().toString()).jsonPath(" [1].id").isEqualTo(tacos[1].getId().toString()).jsonPath("[1].name")
.isEqualTo(“Taco 2”).jsonPath(" [ 11 ] . i d " ) . i s E q u a l T o ( t a c o s [ 11 ] . g e t I d ( ) . t o S t r i n g ( ) ) . j s o n P a t h ( " [11].id") .isEqualTo(tacos[11].getId().toString()) .jsonPath(" [11].id").isEqualTo(tacos[11].getId().toString()).jsonPath("[11].name").isEqualTo(“Taco 12”).jsonPath(" [ 12 ] " ) . d o e s N o t E x i s t ( ) . j s o n P a t h ( " [12]") .doesNotExist().jsonPath(" [12]").doesNotExist().jsonPath("[12]").doesNotExist();

// Test POST Method

TacoRepository tacoRepo = Mockito.mock(
TacoRepository.class);
Mono unsavedTacoMono = Mono.just(testTaco(null));
Taco savedTaco = testTaco(null);
savedTaco.setId(1L);
Mono savedTacoMono = Mono.just(savedTaco);
when(tacoRepo.save(any())).thenReturn(savedTacoMono);
WebTestClient testClient = WebTestClient.bindToController(
new DesignTacoController(tacoRepo)).build();
testClient.post()
.uri("/design")
.contentType(MediaType.APPLICATION_JSON)
.body(unsavedTacoMono, Taco.class)
.exchange()
.expectStatus().isCreated()
.expectBody(Taco.class)
.isEqualTo(savedTaco);

// Testing with a live server
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
public class DesignTacoControllerWebTest {
@Autowired
private WebTestClient testClient;
@Test
public void shouldReturnRecentTacos() throws IOException {
testClient.get().uri("/design/recent")
.accept(MediaType.APPLICATION_JSON).exchange()
.expectStatus().isOk()
.expectBody()
.jsonPath(" [ ? ( @ . i d = = ′ T A C O 1 ′ ) ] . n a m e " ) . i s E q u a l T o ( " C a r n i v o r e " ) . j s o n P a t h ( " [?(@.id == 'TACO1')].name") .isEqualTo("Carnivore") .jsonPath(" [?(@.id==TACO1)].name").isEqualTo("Carnivore").jsonPath("[?(@.id == ‘TACO2’)].name")
.isEqualTo(“Bovine Bounty”)
.jsonPath("$[?(@.id == ‘TACO3’)].name")
.isEqualTo(“Veg-Out”);
}
}
Consume Reactive APIs

Flux ingredients = WebClient.create()
.get()
.uri(“http://localhost:8080/ingredients”)
.retrieve()
.bodyToFlux(Ingredient.class);
ingredients.subscribe(i -> { …})

Flux ingredients = WebClient.create()
.get()
.uri(“http://localhost:8080/ingredients”)
.retrieve()
.bodyToFlux(Ingredient.class);
ingredients
.timeout(Duration.ofSeconds(1))
.subscribe(
i -> { … },
e -> {
// handle timeout error
})

//Handing errors
ingredientMono.subscribe(
ingredient -> {
// handle the ingredient data

},
error-> {
// deal with the error

});

Mono ingredientMono = webClient
.get()
.uri(“http://localhost:8080/ingredients/{id}”, ingredientId)
.retrieve()
.onStatus(HttpStatus::is4xxClientError,
response -> Mono.just(new UnknownIngredientException()))
.bodyToMono(Ingredient.class);
Java 9
jshell

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

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

–release
–class-path instead of -classpath
–version instead of -version
–module-path option has a shortcut -p
更多,见jeps

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

public interface Test {
public static void print() {
System.out.println(“interface print”);
}

default void pout() {System.out.println();
}

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

public interface Test {
private static void print() {
System.out.println(“interface print”);
}

static void pout() {print();
}

}
Optional.ofNullable(date).orElseGet(() -> newDate()); // date为null,才会执行newDate()方法,否则不执行newDate()方法
Optional.ofNullable(date).orElse(newDate()); // 无论date是否为null,都会执行newDate()方法
Java7中,可以使用try-with-Resources

try(Resouce res = …) {
work with res
}
res.close()会被自动执行

例:

try (var in = new Scanner(new FileInputStream(“C:\Users\Young\Desktop\新建文件夹\1.tx.txt”), StandardCharsets.UTF_8);
var out = new PrintWriter(“C:\Users\Young\Desktop\新建文件夹\out.txt”, StandardCharsets.UTF_8)) {
while (in.hasNext()) {
out.println(in.next().toUpperCase());
}
}
in 和 out执行完毕后都会自动关闭资源

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

public static void printAll(String[] lines, PrintWriter out) {
try (out) { // effectively final variable
for (String line : lines) {
out.println(line);
} // out.close() called here
}
}
StackWalker用法示例

public class App {
/**
* Computes the factorial of a number
*
* @param n a non-negative integer
* @return n! = 1 * 2 * . . . * n
*/
public static int factorial(int n) {
System.out.println(“factorial(” + n + “):”);
var walker = StackWalker.getInstance();
walker.forEach(System.out::println);
int r;
if (n <= 1) {
r = 1;
} else {
r = n * factorial(n - 1);
}
System.out.println("return " + r);
return r;
}

public static void main(String[] args) {try (var in = new Scanner(System.in)) {System.out.print("Enter n: ");int n = in.nextInt();factorial(n);}
}

}
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.

ArrayList list = new ArrayList<>(){
@Override
public String get(int index) {
return super.get(index).replaceAll(".","*");
}
};
Java 10
无需定义变量类型,通过var关键字+初始化的值,可以推测出变量类型

var a = 2; // a表示int
var b = “hello”; // b 表示String
var date = new java.util.Date();
var obj = new Custome(); // 自定义对象
Java 11
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”
Pair a = new Pair<>(“A”, “B”);
Pair b = new Pair<>(1.1, 1.11);
System.out.println(a.getClass() == b.getClass()); // TRUE
in Java8

public static Pair makePair(Supplier constr) {
return new Pair<>(constr.get(), constr.get());
}

Pair p = Pair.makePair(String:new);
In general, there is no relationship between Pair and Pair, no matter how S and T are related.

BUT

var managerBuiddies = new Pair(ceo, cfo);
Pair<? extends Employee> buddies = managerBuddies;
Collections
Concurrency
Stream
Java 8

// 流操作
List list = new ArrayList<>();
list.add(1);
list.add(2);
list.parallelStream().filter(i -> i > 1).count();
list.stream().filter(i -> i > 1).count();
Stream words = Stream.of(contents.split(","));
// 创建流
var limits = new BigInteger(“1000”);
Stream integerStream = Stream.iterate(BigInteger.ZERO, n -> n.compareTo(limits) < 0, n -> n.add(BigInteger.ONE));
System.out.println(integerStream.count());
如果我们持有的iterable对象不是集合,那么可以通过下面的调用将其转换成一个流

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

StreamSupport.stream(Spliterators.spliteratorUnknowSize(iterator, Spliterator.ORDERED),false);
至关重要的是,在执行流的操作时,我们并没有修改流背后的集合。记住,流并没有收集其数据,数据一直存储在单独的集合中

Optional

String result = optionalString.orElse(""); // The wrapped string , or “” if none
String result = optionalString.orElseGet(() -> System.getProperty(“myapp.default”));
String result = optionalString.orElseThrow(IllegalStateException::new);
消费Optinal值

optionalValue.ifPresent(v -> result.add(v));
optionalValue.ifPresentOrElse(v -> System.out.println(“Found” + v),
()-> logger.warning(“no match”));
管道化Optional

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

// 如果optionalString的值存在,那么result为optionalString,如果值不存在,那么就会计算lambda表达式,并使用计算出来的结果
Optional transformed = optionalString.or(() -> alternatives.stream().findFirst());
深圳网站建设www.sz886.com

这篇关于Java各版本新增特性, Since Java 8的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/891092

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo