Javascript foreach lambda
Một vấn đề với các lớp ẩn danh là nếu việc triển khai lớp ẩn danh của bạn rất đơn giản, chẳng hạn như một giao diện chỉ chứa một phương thức, thì cú pháp của các lớp ẩn danh có vẻ khó sử dụng và không rõ ràng. Trong những trường hợp này, bạn thường cố gắng chuyển chức năng làm đối số sang phương thức khác, chẳng hạn như hành động nào sẽ được thực hiện khi ai đó nhấp vào nút. Biểu thức lambda cho phép bạn làm điều này, để coi chức năng là đối số của phương thức hoặc mã là dữ liệu Phần trước, Các lớp ẩn danh, chỉ cho bạn cách triển khai một lớp cơ sở mà không cần đặt tên cho nó. Mặc dù điều này thường ngắn gọn hơn so với lớp được đặt tên, nhưng đối với các lớp chỉ có một phương thức, ngay cả một lớp ẩn danh cũng có vẻ hơi thừa và rườm rà. Các biểu thức lambda cho phép bạn thể hiện các thể hiện của các lớp một phương thức một cách gọn gàng hơn Phần này bao gồm các chủ đề sau Giả sử rằng bạn đang tạo một ứng dụng mạng xã hội. Bạn muốn tạo một tính năng cho phép quản trị viên thực hiện bất kỳ loại hành động nào, chẳng hạn như gửi tin nhắn, đối với các thành viên của ứng dụng mạng xã hội đáp ứng các tiêu chí nhất định. Bảng sau mô tả chi tiết trường hợp sử dụng này TrườngMô tảTênThực hiện hành động đối với các thành viên được chọn. Diễn viên chínhQuản trị viênĐiều kiện tiên quyếtQuản trị viên đã đăng nhập vào hệ thống. Hậu điều kiệnHành động chỉ được thực hiện trên các thành viên phù hợp với tiêu chí đã chỉ định. Kịch bản thành công chính
1a. Quản trị viên có tùy chọn xem trước những thành viên phù hợp với tiêu chí đã chỉ định trước khi chỉ định hành động sẽ được thực hiện hoặc trước khi chọn nút Gửi Tần suất xuất hiện Nhiều lần trong ngàyGiả sử rằng các thành viên của ứng dụng mạng xã hội này được đại diện bởi lớp public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 sau public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } } Giả sử rằng các thành viên của ứng dụng mạng xã hội của bạn được lưu trữ trong một thực thể public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }9 Phần này bắt đầu với một cách tiếp cận ngây thơ đối với trường hợp sử dụng này. Nó cải thiện cách tiếp cận này với các lớp ẩn danh và cục bộ, sau đó kết thúc bằng cách tiếp cận ngắn gọn và hiệu quả bằng cách sử dụng các biểu thức lambda. Tìm các đoạn mã được mô tả trong phần này trong ví dụ interface CheckPerson { boolean test(Person p); }0 Một cách tiếp cận đơn giản là tạo ra một số phương thức; . Phương pháp sau đây in các thành viên lớn hơn một độ tuổi được chỉ định public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } } Ghi chú. Một public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }9 là một interface CheckPerson { boolean test(Person p); }2 có thứ tự. Một bộ sưu tập là một đối tượng nhóm nhiều phần tử thành một đơn vị. Bộ sưu tập được sử dụng để lưu trữ, truy xuất, thao tác và truyền đạt dữ liệu tổng hợp. Để biết thêm thông tin về các bộ sưu tập, hãy xem Đường mòn bộ sưu tập Cách tiếp cận này có khả năng làm cho ứng dụng của bạn trở nên giòn, có khả năng ứng dụng không hoạt động do giới thiệu các bản cập nhật (chẳng hạn như các loại dữ liệu mới hơn). Giả sử rằng bạn nâng cấp ứng dụng của mình và thay đổi cấu trúc của lớp public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 sao cho nó chứa các biến thành viên khác nhau; . Bạn sẽ phải viết lại rất nhiều API của mình để phù hợp với thay đổi này. Ngoài ra, cách tiếp cận này là hạn chế không cần thiết; Phương pháp sau đây chung chung hơn interface CheckPerson { boolean test(Person p); }4; public static void printPersonsWithinAgeRange( List roster, int low, int high) { for (Person p : roster) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } } What if you want to print members of a specified sex, or a combination of a specified gender and age range? What if you decide to change the public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 class and add other attributes such as relationship status or geographical location? Although this method is more generic than interface CheckPerson { boolean test(Person p); }4, trying to create a separate method for each possible search query can still lead to brittle code. Thay vào đó, bạn có thể tách mã chỉ định tiêu chí mà bạn muốn tìm kiếm trong một lớp khác Phương pháp sau đây in các thành viên phù hợp với tiêu chí tìm kiếm mà bạn chỉ định public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } } Phương thức này kiểm tra từng trường hợp public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 có trong tham số public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }9 interface CheckPerson { boolean test(Person p); }9 xem nó có thỏa mãn tiêu chí tìm kiếm được chỉ định trong tham số public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60 public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }61 hay không bằng cách gọi phương thức public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }62. Nếu phương thức public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }62 trả về giá trị public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }64, thì phương thức public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }65 được gọi trong trường hợp public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 Để chỉ định tiêu chí tìm kiếm, bạn triển khai giao diện public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60 interface CheckPerson { boolean test(Person p); } Lớp sau triển khai giao diện public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60 bằng cách chỉ định triển khai cho phương thức public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }69. Phương pháp này lọc các thành viên đủ điều kiện tham gia Dịch vụ Chọn lọc tại Hoa Kỳ. nó trả về giá trị public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }64 nếu tham số public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 của nó là nam và trong độ tuổi từ 18 đến 25 public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }6 Để sử dụng lớp này, bạn tạo một thể hiện mới của nó và gọi phương thức public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }65 interface CheckPerson { boolean test(Person p); }1 Mặc dù cách tiếp cận này ít dễ vỡ hơn—bạn không phải viết lại các phương thức nếu bạn thay đổi cấu trúc của public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8—bạn vẫn có mã bổ sung. một giao diện mới và một lớp cục bộ cho mỗi tìm kiếm bạn định thực hiện trong ứng dụng của mình. Bởi vì interface CheckPerson { boolean test(Person p); }14 triển khai một giao diện, bạn có thể sử dụng một lớp ẩn danh thay vì một lớp cục bộ và bỏ qua nhu cầu khai báo một lớp mới cho mỗi lần tìm kiếm Một trong những đối số của lời gọi sau đây của phương thức public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }65 là một lớp ẩn danh lọc các thành viên đủ điều kiện tham gia Dịch vụ Chọn lọc tại Hoa Kỳ. những người là nam và trong độ tuổi từ 18 đến 25 interface CheckPerson { boolean test(Person p); }5 Cách tiếp cận này giảm số lượng mã cần thiết vì bạn không phải tạo một lớp mới cho mỗi tìm kiếm mà bạn muốn thực hiện. Tuy nhiên, cú pháp của các lớp ẩn danh là cồng kềnh vì giao diện public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60 chỉ chứa một phương thức. Trong trường hợp này, bạn có thể sử dụng biểu thức lambda thay vì lớp ẩn danh, như được mô tả trong phần tiếp theo Giao diện public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60 là giao diện chức năng. Giao diện chức năng là bất kỳ giao diện nào chỉ chứa một phương thức trừu tượng. (Một giao diện chức năng có thể chứa một hoặc nhiều phương thức mặc định hoặc phương thức tĩnh. ) Vì giao diện chức năng chỉ chứa một phương thức trừu tượng, bạn có thể bỏ qua tên của phương thức đó khi triển khai nó. Để làm điều này, thay vì sử dụng một biểu thức lớp ẩn danh, bạn sử dụng một biểu thức lambda, được đánh dấu trong lời gọi phương thức sau interface CheckPerson { boolean test(Person p); }8 Xem Cú pháp biểu thức Lambda để biết thông tin về cách xác định biểu thức lambda Bạn có thể sử dụng giao diện chức năng tiêu chuẩn thay cho giao diện public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60, giúp giảm hơn nữa số lượng mã cần thiết Xem xét lại giao diện public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60 interface CheckPerson { boolean test(Person p); } Đây là một giao diện rất đơn giản. Đó là một giao diện chức năng vì nó chỉ chứa một phương thức trừu tượng. Phương thức này nhận một tham số và trả về giá trị interface CheckPerson { boolean test(Person p); }50. Phương pháp này đơn giản đến mức có thể không đáng để xác định một phương pháp trong ứng dụng của bạn. Do đó, JDK xác định một số giao diện chức năng tiêu chuẩn mà bạn có thể tìm thấy trong gói interface CheckPerson { boolean test(Person p); }51 Ví dụ: bạn có thể sử dụng giao diện interface CheckPerson { boolean test(Person p); }52 thay cho public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60. Giao diện này chứa phương thức interface CheckPerson { boolean test(Person p); }54 public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }0 Giao diện interface CheckPerson { boolean test(Person p); }52 là một ví dụ về giao diện chung. (Để biết thêm thông tin về thuốc gốc, hãy xem bài học Thuốc gốc (Đã cập nhật). ) Loại chung (chẳng hạn như giao diện chung) chỉ định một hoặc nhiều tham số loại trong dấu ngoặc nhọn ( interface CheckPerson { boolean test(Person p); }56). Giao diện này chỉ chứa một tham số loại, interface CheckPerson { boolean test(Person p); }57. Khi bạn khai báo hoặc khởi tạo một kiểu chung với các đối số kiểu thực, bạn có một kiểu được tham số hóa. Ví dụ: loại tham số hóa interface CheckPerson { boolean test(Person p); }52 như sau public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }1 Kiểu được tham số hóa này chứa một phương thức có cùng kiểu trả về và các tham số như interface CheckPerson { boolean test(Person p); }59. Do đó, bạn có thể sử dụng interface CheckPerson { boolean test(Person p); }52 thay cho public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60 như phương pháp sau minh họa public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }2 Kết quả là, lời gọi phương thức sau giống như khi bạn gọi public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }65 trong Cách tiếp cận 3. Chỉ định Mã tiêu chí tìm kiếm trong Lớp địa phương để có được các thành viên đủ điều kiện cho Dịch vụ chọn lọc public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }3 Đây không phải là nơi duy nhất có thể sử dụng biểu thức lambda trong phương pháp này. Cách tiếp cận sau gợi ý các cách khác để sử dụng biểu thức lambda Xem xét lại phương thức interface CheckPerson { boolean test(Person p); }83 để xem bạn có thể sử dụng biểu thức lambda ở đâu khác public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }2 Phương thức này kiểm tra từng phiên bản public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 có trong tham số public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }9 interface CheckPerson { boolean test(Person p); }9 xem nó có thỏa mãn các tiêu chí được chỉ định trong tham số interface CheckPerson { boolean test(Person p); }52 public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }61 hay không. Nếu phiên bản public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 đáp ứng các tiêu chí được chỉ định bởi public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }61, thì phương thức interface CheckPerson { boolean test(Person p); }1 được gọi trên phiên bản public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 Thay vì gọi phương thức interface CheckPerson { boolean test(Person p); }1, bạn có thể chỉ định một hành động khác để thực hiện trên các phiên bản public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 đó đáp ứng các tiêu chí được chỉ định bởi public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }61. Bạn có thể chỉ định hành động này bằng biểu thức lambda. Giả sử bạn muốn một biểu thức lambda tương tự như interface CheckPerson { boolean test(Person p); }1, một biểu thức nhận một đối số (một đối tượng thuộc loại public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8) và trả về void. Hãy nhớ rằng, để sử dụng biểu thức lambda, bạn cần triển khai giao diện chức năng. Trong trường hợp này, bạn cần một giao diện chức năng chứa một phương thức trừu tượng có thể nhận một đối số kiểu public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }8 và trả về void. Giao diện interface CheckPerson { boolean test(Person p); }9 chứa phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }00, có các đặc điểm này. Phương thức sau thay thế lời gọi public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }01 bằng một thể hiện của interface CheckPerson { boolean test(Person p); }9 gọi phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }03 public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }5 Kết quả là, lời gọi phương thức sau giống như khi bạn gọi public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }65 trong Cách tiếp cận 3. Chỉ định Mã tiêu chí tìm kiếm trong Lớp địa phương để có được các thành viên đủ điều kiện cho Dịch vụ chọn lọc. Biểu thức lambda được sử dụng để in các thành viên được tô sáng public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }6 Điều gì sẽ xảy ra nếu bạn muốn làm nhiều việc hơn với hồ sơ thành viên của mình hơn là in chúng ra. Giả sử bạn muốn xác thực hồ sơ của các thành viên hoặc truy xuất thông tin liên hệ của họ? . Giao diện public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }05 chứa phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }06. Phương thức sau truy xuất dữ liệu được chỉ định bởi tham số public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }07, sau đó thực hiện một hành động trên dữ liệu được chỉ định bởi tham số public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }08 public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }7 Phương pháp sau lấy địa chỉ email từ mỗi thành viên có trong interface CheckPerson { boolean test(Person p); }9 đủ điều kiện cho Dịch vụ Chọn lọc và sau đó in nó public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }8 Xem xét lại phương pháp public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }10. Sau đây là phiên bản chung của nó chấp nhận, như một tham số, một bộ sưu tập chứa các phần tử của bất kỳ kiểu dữ liệu nào public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }9 Để in địa chỉ e-mail của các thành viên đủ điều kiện tham gia Dịch vụ Chọn lọc, hãy gọi phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }11 như sau public static void printPersonsWithinAgeRange( List roster, int low, int high) { for (Person p : roster) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } }0 Lời gọi phương thức này thực hiện các hành động sau
Bạn có thể thay thế từng thao tác này bằng một thao tác tổng hợp Ví dụ sau sử dụng các thao tác tổng hợp để in địa chỉ e-mail của những thành viên có trong bộ sưu tập interface CheckPerson { boolean test(Person p); }9 đủ điều kiện tham gia Dịch vụ Chọn lọc public static void printPersonsWithinAgeRange( List roster, int low, int high) { for (Person p : roster) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } }1 Bảng sau đây ánh xạ từng thao tác mà phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }11 thực hiện với thao tác tổng hợp tương ứng public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }11 ActionAggregate OperationObtain a source of objects public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }31Filter objects that match a interface CheckPerson { boolean test(Person p); }52 object public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }33Map objects to another value as specified by a public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }05 object public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }35Perform an action as specified by a interface CheckPerson { boolean test(Person p); }9 object public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }37 Các hoạt động public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }38, public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }39 và public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }40 là các hoạt động tổng hợp. Các hoạt động tổng hợp xử lý các phần tử từ một luồng chứ không phải trực tiếp từ một tập hợp (đó là lý do tại sao phương thức đầu tiên được gọi trong ví dụ này là public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }41). Luồng là một dãy các phần tử. Không giống như một bộ sưu tập, nó không phải là một cấu trúc dữ liệu lưu trữ các phần tử. Thay vào đó, một luồng mang các giá trị từ một nguồn, chẳng hạn như bộ sưu tập, thông qua một đường dẫn. Đường ống là một chuỗi các hoạt động truyền phát, trong ví dụ này là public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }38- public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }39- public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }40. Ngoài ra, các hoạt động tổng hợp thường chấp nhận các biểu thức lambda làm tham số, cho phép bạn tùy chỉnh cách chúng hoạt động Để thảo luận kỹ hơn về các phép toán tổng hợp, hãy xem bài học Các phép toán tổng hợp Để xử lý các sự kiện trong ứng dụng giao diện người dùng đồ họa (GUI), chẳng hạn như thao tác bàn phím, thao tác chuột và thao tác cuộn, bạn thường tạo trình xử lý sự kiện, thường liên quan đến việc triển khai một giao diện cụ thể. Thông thường, giao diện xử lý sự kiện là giao diện chức năng; Trong ví dụ JavaFX public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }45 (đã thảo luận trong phần trước Lớp ẩn danh), bạn có thể thay thế lớp ẩn danh được đánh dấu bằng biểu thức lambda trong câu lệnh này public static void printPersonsWithinAgeRange( List roster, int low, int high) { for (Person p : roster) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } }2 Lời gọi phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }46 chỉ định điều gì sẽ xảy ra khi bạn chọn nút được đại diện bởi đối tượng public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }47. Phương thức này yêu cầu một đối tượng kiểu public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }48. Giao diện public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }48 chỉ chứa một phương thức, public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }50. Giao diện này là một giao diện chức năng, vì vậy bạn có thể sử dụng biểu thức lambda được đánh dấu sau đây để thay thế nó public static void printPersonsWithinAgeRange( List roster, int low, int high) { for (Person p : roster) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } }3 Một biểu thức lambda bao gồm những điều sau đây
Lưu ý rằng một biểu thức lambda trông rất giống một khai báo phương thức; Ví dụ sau, public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }56, là một ví dụ về biểu thức lambda nhận nhiều hơn một tham số hình thức public static void printPersonsWithinAgeRange( List roster, int low, int high) { for (Person p : roster) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } }8 Phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }57 thực hiện phép toán trên hai toán hạng số nguyên. Bản thân hoạt động được chỉ định bởi một phiên bản của public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }58. Ví dụ định nghĩa hai thao tác với biểu thức lambda, public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }59 và public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }60. Ví dụ in như sau public static void printPersonsWithinAgeRange( List roster, int low, int high) { for (Person p : roster) { if (low <= p.getAge() && p.getAge() < high) { p.printPerson(); } } }9 Giống như các lớp ẩn danh và cục bộ, các biểu thức lambda có thể nắm bắt các biến; . Tuy nhiên, không giống như các lớp ẩn danh và cục bộ, các biểu thức lambda không có bất kỳ vấn đề về đổ bóng nào (xem phần Đổ bóng để biết thêm thông tin). Biểu thức lambda có phạm vi từ vựng. Điều này có nghĩa là chúng không kế thừa bất kỳ tên nào từ siêu kiểu hoặc giới thiệu một cấp phạm vi mới. Declarations in a lambda expression are interpreted just as they are in the enclosing environment. Ví dụ sau đây, public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }61, chứng minh điều này public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }0 Ví dụ này tạo ra đầu ra sau public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }1 Nếu bạn thay thế tham số public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }62 ở vị trí của public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }63 trong phần khai báo của biểu thức lambda public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }64, thì trình biên dịch sẽ tạo ra lỗi public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }2 Trình biên dịch tạo ra lỗi "Tham số x của biểu thức Lambda không thể khai báo lại một biến cục bộ khác được xác định trong phạm vi kèm theo" vì biểu thức lambda không đưa ra mức phạm vi mới. Do đó, bạn có thể truy cập trực tiếp các trường, phương thức và biến cục bộ của phạm vi kèm theo. Ví dụ: biểu thức lambda truy cập trực tiếp tham số public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }62 của phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }66. Để truy cập các biến trong lớp kèm theo, hãy sử dụng từ khóa public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }67. Trong ví dụ này, public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }68 đề cập đến biến thành viên public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }69 Tuy nhiên, giống như các lớp ẩn danh và cục bộ, biểu thức lambda chỉ có thể truy cập các biến cục bộ và tham số của khối kèm theo là cuối cùng hoặc có hiệu lực cuối cùng. Trong ví dụ này, biến public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }70 có hiệu lực cuối cùng; . Tuy nhiên, giả sử rằng bạn thêm câu lệnh gán sau vào biểu thức lambda public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }64 public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }3 Do câu lệnh gán này, biến public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }70 không còn là giá trị cuối cùng nữa. Do đó, trình biên dịch Java tạo ra một thông báo lỗi tương tự như "Biến cục bộ z được xác định trong phạm vi kèm theo phải là cuối cùng hoặc có hiệu lực cuối cùng" Làm cách nào để bạn xác định loại biểu thức lambda? public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }4 Biểu thức lambda này đã được sử dụng trong hai phương thức sau Khi thời gian chạy Java gọi phương thức public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }65, nó sẽ mong đợi một loại dữ liệu là public class Person { public enum Sex { MALE, FEMALE } String name; LocalDate birthday; Sex gender; String emailAddress; public int getAge() { // ... } public void printPerson() { // ... } }60, vì vậy biểu thức lambda thuộc loại này. Tuy nhiên, khi thời gian chạy Java gọi phương thức interface CheckPerson { boolean test(Person p); }83, nó sẽ mong đợi một loại dữ liệu là interface CheckPerson { boolean test(Person p); }52, vì vậy biểu thức lambda thuộc loại này. Kiểu dữ liệu mà các phương thức này mong đợi được gọi là kiểu đích. Để xác định loại biểu thức lambda, trình biên dịch Java sử dụng loại mục tiêu của ngữ cảnh hoặc tình huống trong đó biểu thức lambda được tìm thấy. Theo đó, bạn chỉ có thể sử dụng các biểu thức lambda trong các tình huống mà trình biên dịch Java có thể xác định loại mục tiêu
Đối với các đối số phương thức, trình biên dịch Java xác định loại mục tiêu với hai tính năng ngôn ngữ khác. overload resolution and type argument inference Xem xét hai giao diện chức năng sau ( public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }78 và public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }79) public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }5 Phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }80 không trả về giá trị, trong khi đó public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }81 thì không Giả sử rằng bạn đã nạp chồng phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }82 như sau (xem Xác định phương thức để biết thêm thông tin về các phương thức nạp chồng) public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }6 Phương thức nào sẽ được gọi trong câu lệnh sau? public static void printPersons( List roster, CheckPerson tester) { for (Person p : roster) { if (tester.test(p)) { p.printPerson(); } } }7 Phương thức public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }83 sẽ được gọi vì phương thức đó trả về một giá trị; . Trong trường hợp này, loại biểu thức lambda public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }85 là public static void printPersonsOlderThan(List roster, int age) { for (Person p : roster) { if (p.getAge() >= age) { p.printPerson(); } } }86 Bạn có thể tuần tự hóa một biểu thức lambda nếu loại mục tiêu và các đối số đã bắt của nó có thể tuần tự hóa được. Tuy nhiên, giống như các lớp bên trong, việc tuần tự hóa các biểu thức lambda không được khuyến khích |