Một số tính năng quan trọng của Java 8 là:
- phương thức forEach () trong interface có thể lặp lại
- các phương thức default và static trong Interface
- Chức năng Interface và biểu thức Lambda
- Java Stream API cho các hoạt động dữ liệu hàng loạt trên collections
- Java Time API
- Cải tiến Collection API
- Cải tiến Concurrency API
- Cải tiến Java IO
- Cải tiến API cốt lõi khác
Hãy cùng tìm hiểu sơ lược về các tính năng Java 8 này. Tôi sẽ cung cấp một số đoạn mã để bạn hiểu rõ hơn, vì vậy nếu bạn muốn chạy các chương trình trong Java 8, bạn sẽ phải thiết lập môi trường Java 8 theo các bước sau.
👉 Tải xuống Eclipse IDE mới nhất, nó cung cấp hỗ trợ cho java 8 ngay bây giờ. Đảm bảo rằng đường dẫn xây dựng dự án của bạn đang sử dụng thư viện Java 8.
Bất cứ khi nào chúng ta cần duyệt qua một Collection, chúng ta cần tạo Iterator Collection có mục đích toàn bộ là để lặp lại và sau đó chúng ta có logic nghiệp vụ trong một vòng lặp cho từng phần tử trong Collection. Chúng ta có thể nhận được ConcurrentModificationException nếu trình lặp không được sử dụng đúng cách.
Java 8 đã giới thiệu phương thức forEach trong interface java.lang.Iterable để trong khi viết mã, chúng ta chỉ tập trung vào logic nghiệp vụ. Phương thức forEach lấy java.util.function. Consumer làm đối số, vì vậy nó giúp ích cho việc đặt logic nghiệp vụ của chúng ta ở một vị trí riêng biệt mà chúng ta có thể sử dụng lại. Hãy xem cách sử dụng forEach với ví dụ đơn giản.
package com.codetimes90.Java8ForEach;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Consumer;
public class Java8ForeachExample {
public static void main(String[] arg) {
//Tao
mot collection mau
List<Integer> myList = new ArrayList<Integer>();
for(int i=0; i<10; i++) myList.add(i);
//duyệt
qua bằng Iterator
Iterator<Integer> it = myList.iterator();
while (it.hasNext())
{
Integer i = it.next();
System.out.println("Itertor value: " + i);
}
//duyệt
qua forEach phương thức của Iterable với
anonymous class
myList.forEach(new Consumer<Integer>() {
public void accept(Integer t) {
System.out.println("forEach value: "+ t);
}
});
//duyệt
với Consumer interface
MyConsumer action = new MyConsumer();
myList.forEach(action);
}
}
//Triển
khai #Consumer có thể được sử dụng lại
class MyConsumer implements Consumer<Integer>{
public void accept(Integer t) {
System.out.println("Consumer impl Value::"+t);
}
}
Số lượng dòng có thể tăng lên nhưng phương thức forEach giúp có logic cho việc lặp lại và logic nghiệp vụ ở vị trí riêng biệt, dẫn đến việc phân tách mối quan tâm cao hơn và mã sạch hơn.
2. các phương thức default và static trong Interface
Nếu bạn đọc chi tiết phương thức forEach một cách cẩn thận, bạn sẽ nhận thấy rằng nó được định nghĩa trong Iterable Interface nhưng chúng tôi biết rằng các interface không thể có thân phương thức. Từ Java 8, các interface được cải tiến để có phương pháp triển khai. Chúng ta có thể sử dụng từ khóa default và static để tạo interface với việc triển khai phương thức. Việc triển khai phương thức forEach trong Iterable interface là:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
package com.codetimes90.Java8.defaultmethod;
@FunctionalInterface
public interface Interface1 {
void method1( String str);
default void log(String str) {
System.out.println("I1 logging: "+ str);
}
static void print(String str) {
System.out.println("Painting " + str);
}
// cố gắng
ghi đè phương thức Object sẽ gây ra
lỗi #compiletime là
//A default
method cannot override a method from java.lang.Object "
// default String toString() {
// return
"i1";
// }
}
@FunctionalInterface
public interface Interface2 {
void method2();
default void log(String str) {
System.out.println("I2 logging: "+ str);
}
}
package com.codetimes90.Java8.defaultmethod;
public class MyClass implements Interface1, Interface2 {
@Override
public void method2() {}
@Override
public void method1(String str) {}
@Override
public void log(String str){
System.out.println("MyClass logging::"+str);
Interface1.print("abc");
}
}
Như bạn có thể thấy rằng Interface1 có triển khai phương thức static được sử dụng trong MyClass.log() triển khai phương thức. Java 8 sử dụng nhiều phương thức default và static trong Collection API và các phương thức default được thêm vào để mã của chúng tôi vẫn tương thích ngược.
Nếu bất kỳ lớp nào trong hệ thống phân cấp có một phương thức có cùng chữ ký, thì các phương thức default trở nên không liên quan. Vì bất kỳ lớp nào triển khai một interface đã có Object là lớp cha, nếu chúng ta có các phương thức default equals(), hashCode() trong interface, nó sẽ trở nên không liên quan. Đó là lý do tại sao để rõ ràng hơn, các interface không được phép có các phương thức default của Đối tượng.
Để biết chi tiết đầy đủ về các thay đổi interface trong Java 8, vui lòng đọc các thay đổi giao diện Java 8 .
3. Functional interface và biểu thức Lambda
Nếu bạn nhận thấy code interface ở trên, bạn sẽ thấy chú thích @F FunctionInterface. Functional interface là khái niệm mới được giới thiệu trong Java 8. Một interface với chính xác một phương thức trừu tượng sẽ trở thành Functional interface. Chúng ta không cần sử dụng chú thích @FunctionInterface để đánh dấu interface là Functional interface. Chú thích @FunctionInterface là một cơ sở để tránh tình cờ bổ sung các phương thức trừu tượng trong các functional interface. Bạn có thể nghĩ về nó giống như chú thích @Override và cách tốt nhất là sử dụng nó. java.lang.Runnable với phương thức trừu tượng duy nhất run() là một ví dụ tuyệt vời về functional interface.
Một trong những lợi ích chính của functional interface là khả năng sử dụng các biểu thức lambda để khởi tạo chúng. Chúng ta có thể tạo một interface với lớp ẩn danh nhưng mã trông cồng kềnh.
Runnable
r = new Runnable(){
@Override
public void run() {
System.out.println("My Runnable");
}};
Runnable
r1 = () -> {
System.out.println("My Runnable");
};
Interface1
i1 = (s) -> System.out.println(s);
i1.method1("abc");
Vì vậy, các biểu thức lambda là một phương tiện để tạo các lớp ẩn danh của các functional interface một cách dễ dàng. Không có lợi ích về runtime khi sử dụng biểu thức lambda, vì vậy tôi sẽ sử dụng nó một cách thận trọng vì tôi không ngại viết thêm một vài dòng mã.
Một gói mới java.util.function đã được thêm vào với một loạt các functional interface để cung cấp các kiểu đích cho các biểu thức lambda và các tham chiếu phương thức. Biểu thức Lambda là một chủ đề rất lớn, tôi sẽ viết một bài riêng về vấn đề đó trong tương lai.
Bạn có thể đọc hướng dẫn đầy đủ tại Hướng dẫn biểu thức Lambda Java 8.
4. Java Stream API cho các hoạt động dữ liệu hàng loạt trên bộ sưu tập
Một tính năng mới java.util.stream đã được thêm vào trong Java 8 để thực hiện các thao tác lọc / ánh xạ / giảm như với Collection. Stream API sẽ cho phép thực thi tuần tự cũng như song song. Đây là một trong những tính năng tốt nhất đối với tôi vì tôi làm việc rất nhiều với Collection và thông thường với BigData, chúng tôi cần lọc ra chúng dựa trên một số điều kiện.
Collection interface đã được mở rộng với stream() và parallelStream() phương pháp mặc định để có được Stream để thực hiện tuần tự và song song. Hãy xem cách sử dụng của họ với ví dụ đơn giản.
package com.codetimes90.Java8;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class streamExample {
public static void main(String[] args) {
List<Integer> myList = new ArrayList<>();
for(int i=0; i<100; i++) myList.add(i);
//stream
tuan tu
Stream<Integer> sequentialStream = myList.stream();
//stream
song song
Stream<Integer> parallelStream = myList.parallelStream();
//using
lambda with Stream API, filter example
Stream<Integer> highNums = parallelStream.filter(p ->p > 90);
//using
lambda in forEach
highNums.forEach(p->System.out.println("High Nums parallel="+p));
Stream<Integer> highNumsSeq = sequentialStream.filter(p->p>90);
highNumsSeq.forEach(p->System.out.println("High Nums sequential="+p));
}
}
High Nums parallel=91
High
Nums parallel=96
High
Nums parallel=93
High
Nums parallel=98
High
Nums parallel=94
High
Nums parallel=95
High
Nums parallel=97
High
Nums parallel=92
High
Nums parallel=99
High
Nums sequential=91
High
Nums sequential=92
High Nums
sequential=93
High
Nums sequential=94
High
Nums sequential=95
High
Nums sequential=96
High
Nums sequential=97
High
Nums sequential=98
High Nums sequential=99
Lưu ý rằng các giá trị xử lý song song không theo thứ tự, vì vậy xử lý song song sẽ rất hữu ích khi làm việc với các bộ sưu tập lớn.
Không thể đề cập đến mọi thứ về Stream API trong bài đăng này, bạn có thể đọc mọi thứ về Stream API tại Hướng dẫn ví dụ về Stream API trong Java 8.
5. Java Time API
Luôn luôn khó làm việc với Date, Time và Time Zones trong java. Không có phương pháp tiếp cận tiêu chuẩn hoặc API trong java cho Date và Time trong Java. Một trong những bổ sung tuyệt vời trong Java 8 là time java.time sẽ hợp lý hóa quá trình làm việc với Time trong java.
Chỉ cần nhìn vào các gói Java Time API, tôi có thể cảm nhận rằng nó sẽ rất dễ sử dụng. Nó có một số gói java.time.format con cung cấp các lớp để in và phân tích cú pháp Date và Time, đồng thời java.time.zone cung cấp hỗ trợ cho Time Zones và các quy tắc của chúng.
Time API mới thích enums hơn hằng số Integer cho months và date trong tuần. Một trong những lớp hữu ích là DateTimeFormatter để chuyển đổi các đối tượng DateTime thành chuỗi.
Để có hướng dẫn đầy đủ, hãy xem Hướng dẫn ví dụ về API ngày giờ của Java .
6. Cải tiến Collection API
Chúng tôi đã thấy phương thức forEach() và Stream API cho các Collection. Một số phương pháp mới được thêm vào Collection API là:
👉 Phương thức mặc định Iterator: forEachRemaining(Consumer action) để thực hiện hành động đã cho cho từng phần tử còn lại cho đến khi tất cả các phần tử đã được xử lý hoặc hành động ném ra một ngoại lệ.
👉 Phương thức mặc định Collection: removeIf(Predicate filter) để loại bỏ tất cả các phần tử của tập hợp này thỏa mãn vị từ đã cho.
👉 Collection: phương thức spliterator() trả về cá thể Spliterator có thể được sử dụng để duyệt các phần tử tuần tự hoặc song song.
👉 Ánh xạ các phương thức ReplaceAll(), compute(), merge().
👉 Cải thiện hiệu suất cho lớp HashMap với KeyCollisions
7. Cải tiến concurrency API
Một số cải tiến concurrent API quan trọng là:
👉 ConcurrentHashMap các phương thức compute(), forEach(), forEachEntry(), forEachKey(), forEachValue(), merge(), Reduce() và search().
👉 CompletableFuture có thể được hoàn thành một cách rõ ràng (thiết lập giá trị và trạng thái của nó).
👉 Phương thức Executor newWorkStealingPool() để tạo nhóm luồng đánh cắp công việc bằng cách sử dụng tất cả các bộ xử lý có sẵn làm cấp độ song song mục tiêu của nó.
8. Cải tiến Java IO
Một
số cải tiến IO mà tôi biết là:
👉 Files.list(Path dir) trả về một Stream được điền lười biếng, các phần tử của chúng là các mục nhập trong thư mục.
👉 Files.lines(Path path) đọc tất cả các dòng từ một tệp dưới dạng Stream.
👉 Files.find() sẽ trả về Stream được điền một cách lười biếng bằng Path bằng cách tìm kiếm các tệp trong cây tệp được bắt nguồn từ một tệp bắt đầu nhất định.
👉 BufferedReader.lines() trả về một Stream, các phần tử của chúng là các dòng được đọc từ BufferedReader này.
9. Cải tiến API cốt lõi khác
1. Phương thức Static ThreadLocal withInitial(Supplier supplier) để tạo phiên bản dễ dàng.
2. Comparator interface đã được mở rộng với rất nhiều phương thức default và static cho thứ tự tự nhiên, thứ tự ngược lại, v.v.
3. các phương thức min(), max() và sum() trong các lớp Integer, Long và Double wrapper.
4. Các phương thức logicAnd(), logicOr() và logicXor() trong lớp Boolean.
5. Phương thức ZipFile .stream() để lấy Stream có thứ tự qua các mục tệp ZIP. Các mục nhập xuất hiện trong Stream theo thứ tự xuất hiện trong thư mục trung tâm của tệp ZIP.
6. Một số phương pháp tiện ích trong lớp Math.
7. jjs lệnh được thêm vào để gọi Nashorn Engine.
8. jdeps lệnh được thêm vào để phân tích các tệp lớp
9. JDBC-ODBC Bridge đã bị xóa.
10. Không gian bộ nhớ PermGen đã bị xóa

0 Nhận xét