API luồng là gì?
API Stream là một cách mới để làm việc với cấu trúc dữ liệu theo kiểu chức năng. API luồng (mô tả về cách thức mà một chương trình máy tính có thể giao tiếp với chương trình khác), cốt lõi của nó là một luồng dữ liệu. Bản thân thuật ngữ “luồng” khá mơ hồ trong lập trình nói chung và trong Java nói riêng.List<String> list = new ArrayList<String>();
list.add("One");
list.add("Two");
list.add("Three");
list.add("Four");
list.add("Five");
list.add("Six");
list.add("Seven");
list.add("Eight");
list.add("Nine");
list.add("Ten");
Stream stream = list.stream();
Như đã đề cập ở trên, API Stream cho phép bạn giảm số dòng mã. Ví dụ với một luồng:
IntStream.of(50, 60, 70, 80, 90, 100, 110, 120).filter(x -> x < 90).map(x -> x + 10)
.limit(3).forEach(System.out::print);
Ví dụ không có chủ đề:
int[] arr = {50, 60, 70, 80, 90, 100, 110, 120
int count = 0;
for (int x : arr) {
if (x >= 90) continue;
x += 10;
count++;
if (count > 3) break;
System.out.print(x);
}
Các cách có thể để tạo Luồng:
- Luồng trống:
Stream.empty()
- Truyền phát từ Danh sách:
list.stream()
- Truyền phát từ Bản đồ:
map.entrySet().stream()
- Truyền phát từ mảng:
Arrays.stream(array)
- Truyền phát từ các phần tử được chỉ định:
Stream.of("1", "2", "3")
- Trung gian (còn gọi là "lười biếng") - xử lý các phần tử đến và trả về luồng. Có thể có nhiều toán tử trung gian trong chuỗi xử lý phần tử.
- Terminal (“terminal”, còn được gọi là “eager”) - xử lý các phần tử và kết thúc luồng, do đó chỉ có thể có một toán tử đầu cuối trong chuỗi.
1.List<String> list = new ArrayList<String>();
2.list.add("One");
…
11.list.add("Ten");
12.Stream stream = list.stream();
13.stream.filter(x-> x.toString().length() == 3).forEach(System.out::println);
Những gì đang xảy ra ở đây:
- 1 - tạo danh sách
list
; - 2-11 - điền dữ liệu thử nghiệm vào đó;
- 12 - tạo một đối tượng
Stream
; - 13 - phương thức
filter
(bộ lọc) - toán tử trung gian,x
tương đương với một phần tử của bộ sưu tập để liệt kê (như vớifor each
) và sau -> chúng tôi chỉ ra cách bộ sưu tập của chúng tôi được lọc và vì đây là toán tử trung gian nên bộ sưu tập được lọc sẽ đi sâu hơn vào phương thức ,forEach
đến lượt nó là phần cuối (cuối cùng) tương tự của phép liệt kêfor each
(Biểu thức viếtSystem.out::println
tắt của:,x-> System.out.println(x))
lần lượt đi qua tất cả các phần tử của bộ sưu tập được truyền cho nó và hiển thị nó)
- Quá trình xử lý sẽ không bắt đầu cho đến khi toán tử đầu cuối được gọi.
list.stream().filter(s -> s > 5)
(sẽ không lấy một phần tử nào từ danh sách); - Một phiên bản của luồng không thể được sử dụng nhiều lần =( ;
Vì vậy, mỗi khi nó mới:
list.stream().filter(x-> x.toString().length() == 3).forEach(System.out::println);
list.stream().forEach(x -> System.out.println(x));
Có thể có nhiều toán tử trung gian được gọi trên một luồng, trong khi chỉ có một toán tử đầu cuối:
stream.filter(x-> x.toString().length() == 3).map(x -> x + " - the length of the letters is three").forEach(x -> System.out.println(x));
filter(Predicate predicate)
lọc luồng, chỉ truyền những phần tử đáp ứng điều kiện (Vị ngữ là giao diện chức năng tích hợp được thêm vào gói trong Java SE 8.java.util.function
Kiểm tra giá trị cho “ true ” và “ false ”);map(Function mapper)
cho phép tạo một hàm mà chúng ta sẽ thay đổi từng thành phần và bỏ qua nó thêm (Giao diện chức năng thểFunction<T,R>
hiện chức năng chuyển đổi từ một đối tượng loại T sang đối tượng loại R)flatMap(Function<T, Stream<R>> mapper)
- như trong trường hợpmap
, chúng được sử dụng để chuyển đổi thành luồng nguyên thủy.
[stream1,stream2,stream3,stream4] => stream
:
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convert the word to an array of letters
.flatMap(Arrays::stream).distinct() //aligns each generated thread into a single thread
.collect(Collectors.toList()).forEach(System.out::println);
Trong khi map
nó chuyển đổi thành danh sách các chủ đề (chính xác hơn là <Stream>
các chủ đề) [stream1,stream2,stream3,stream4] =>Stream.of(stream1,stream2,stream3,stream4)
:
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convert the word to an array of letters
.map(Arrays::stream).distinct() //Make the array into a separate thread
.collect(Collectors.toList()).forEach(System.out::println);
Một điểm khác biệt so với map
, bạn có thể chuyển đổi một phần tử thành 0, một hoặc nhiều phần tử khác. Để chuyển đổi một phần tử thành phần tử 0, bạn cần trả về null
hoặc một luồng trống. Để chuyển đổi thành một phần tử, bạn cần trả về một luồng từ một phần tử, ví dụ: thông qua Stream.of(x)
. Để trả về một số phần tử, bạn có thể tạo luồng có các phần tử này bằng bất kỳ cách nào. Cùng một phương thức FlatMap, nhưng dành cho Double, Integer và Long:
- FlatMapToDouble(Trình ánh xạ hàm)
- FlatMapToInt(Trình ánh xạ hàm)
- FlatMapToLong(Trình ánh xạ hàm)
Stream.of(2, 3, 0, 1, 3)
.flatMapToInt(x -> IntStream.range(0, x))
.forEach(System.out::print);// 010120012
-
IntStream.range(0,x) – xuất các phần tử từ 0 (đã bao gồm) đến x (không bao gồm) vào luồng;
bản đồ:
Stream.of(2, 3, 0, 1, 3) .map(x -> IntStream.range(0, x)) .forEach(System.out::print);//list of streams (streams);
-
limit(long maxSize) – giới hạn luồng theo số phần tử:
stream.limit(5).forEach(x -> System.out.println(x));
-
Skip(long n) – bỏ qua n phần tử:
stream.skip(3).forEach(x -> System.out.println(x));
-
được sắp xếp()
- được sắp xếp (Bộ so sánh so sánh) - sắp xếp luồng (sắp xếp như TreeMap):
stream.sorted().forEach(x -> System.out.println(x));
-
khác biệt() - kiểm tra luồng xem tính duy nhất của các phần tử (loại bỏ sự lặp lại của các phần tử);
-
dropwhile(Predicate predicate) - bỏ qua các phần tử thỏa mãn điều kiện (xuất hiện trong java 9, Giao diện chức năng Predicate<T> kiểm tra xem một số điều kiện có được đáp ứng hay không. Nếu nó được đáp ứng, thì trả về true. Biểu thức lambda nhận một đối tượng thuộc loại T làm tham số:
Predicate<Integer> isPositive = x -> x > 0; System.out.println(isPositive.test(3)); // true System.out.println(isPositive.test(-9)); // false
-
forEach(Consumer action) – tương tự for each (Consumer<T> thực hiện một số hành động trên một đối tượng thuộc loại T mà không trả lại bất cứ thứ gì);
-
count() – trả về số phần tử luồng:
System.out.println(stream.count());
-
coll(Collector Collector) – phương thức thu thập tất cả các phần tử vào một danh sách, tập hợp hoặc bộ sưu tập khác, nhóm các phần tử theo tiêu chí nào đó, kết hợp mọi thứ thành một chuỗi, v.v.:
List<String> list = Stream.of(“One”, “Two”, “Three”).collect(Collectors.toList());
-
collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
- giống như ,collect(collector)
chỉ có các tham số được chia nhỏ để thuận tiện (supplier
ví dụ: cung cấp các đối tượng mới (vùng chứa),new ArrayList()
thêmaccumulator
một phần tử vào vùng chứa,combiner
kết hợp các phần của luồng với nhau); -
giảm (T nhận dạng, bộ tích lũy BinaryOperator) - chuyển đổi tất cả các phần tử của luồng thành một đối tượng (tính tổng của tất cả các phần tử hoặc tìm phần tử tối thiểu), trước tiên lấy đối tượng và phần tử
identity
đầu tiên của luồng, áp dụng hàmaccumulator
vàidentity
trở thành kết quả của nó. Sau đó mọi thứ tiếp tục cho các phần tử còn lại.int sum = Stream.of(1, 2, 3, 4, 5).reduce(10, (acc, x) -> acc + x);// = 25
-
reduce(BinaryOperator accumulator)
— phương thức tương tự như trên nhưng phương thức ban đầu bị thiếuidentity
, nó là phần tử đầu tiên của luồngOptional min(Comparator comparator)
Tùy chọn tối đa (Bộ so sánh so sánh) tìm kiếm phần tử tối thiểu/tối đa dựa trên bộ so sánh đã qua; -
findFirst()
– lấy ra phần tử đầu tiên của luồng:Stream.of(1, 2, 3, 4, 9).findFirst();
-
allMatch(Predicate predicate)
— trả về true nếu tất cả các phần tử của luồng thỏa mãn điều kiện. Nếu gặp bất kỳ phần tử nào mà kết quả của việc gọi hàm vị ngữ là sai thì toán tử sẽ ngừng quét các phần tử đó và trả về false :Stream.of(1, 2, 3, 4, 9).allMatch(x -> x <= 7);//false
-
anyMatch(Predicate predicate)
— sẽ trả về true nếu ít nhất một phần tử của luồng thỏa mãn điều kiệnpredicate
:Stream.of(1, 2, 3, 4, 9).anyMatch(x -> x >= 7);//true
-
noneMatch(Predicate predicate)
— sẽ trả về true nếu sau khi xem qua tất cả các phần tử của luồng, không có phần tử nào thỏa mãn điều kiệnpredicate
:Stream.of(1, 2, 3, 4, 9).noneMatch(x -> x >= 7);//false
Collectors
:
-
toList()
- tập hợp các phần tử thànhList
:List<Integer> list = Stream.of(99, 2, 3).collect(Collectors.toList());
-
toSet()
- tập hợp các phần tử thành một tập hợp:Set<Integer> set = Stream.of(99, 2, 3).collect(Collectors.toSet());
-
counting()
- Đếm số phần tử:Long count = Stream.of("1", "2", "3", "4").collect(Collectors.counting());
-
joining()
-
joining(CharSequence delimiter)
-
joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
- tập hợp các phần tử thành một dòng. Ngoài ra, bạn có thể chỉ định dấu phân cách cũng như tiền tố và hậu tố cho toàn bộ chuỗi:String a = Stream.of("s", "u" ,"p", "e", "r").collect(Collectors.joining()); System.out.println(a); // super String b = Stream.of("s", "u", "p", "e", "r").collect(Collectors.joining("-")); System.out.println(b); // s-u-p-e-r String c = Stream.of("s", "u", "p", "e", "r").collect(Collectors.joining(" -> ", "[ ", " ]")); System.out.println(c); // [ s -> u -> p -> e -> r ]
-
summingInt(ToIntFunction mapper)
-
summingLong(ToLongFunction mapper)
-
summingDouble(ToDoubleFunction mapper)
- một bộ sưu tập chuyển đổi các đối tượng thành int/long/double và tính tổng.
GO TO FULL VERSION