tek4

Biểu thức Lambda trong Java

by - September. 26, 2021
Kiến thức
Học
Công nghệ
<p>Trong b&agrave;i viết n&agrave;y, ch&uacute;ng ta sẽ t&igrave;m hiểu về biểu thức Lambda trong Java v&agrave; c&aacute;ch sử dụng c&ugrave;ng với c&aacute;c giao diện chức năng, c&ugrave;ng với c&aacute;c v&iacute; dụ dẫn chứng.</p> <p>Biểu thức Lambda được giới thiệu lần đầu ti&ecirc;n trong Java 8. Mục ti&ecirc;u ch&iacute;nh của n&oacute; l&agrave; tăng sức mạnh cho việc biểu đạt của ng&ocirc;n ngữ. Tuy nhi&ecirc;n, trước khi đi v&agrave;o biểu thức Lambda, trước ti&ecirc;n ch&uacute;ng ta cần hiểu c&aacute;c giao diện chức năng.</p> <h2>Giao diện chức năng l&agrave; g&igrave;?</h2> <p>Nếu một giao diện trong Java chứa một v&agrave; chỉ một phương thức trừu tượng th&igrave; n&oacute; được gọi l&agrave; giao diện chức năng. Phương thức duy nhất n&agrave;y sẽ x&aacute;c định mục đ&iacute;ch của giao diện.</p> <p>V&iacute; dụ: Giao diện Runnable từ g&oacute;i java.lang; l&agrave; một giao diện chức năng v&igrave; n&oacute; chỉ tạo một phương thức l&agrave; run().</p> <p>C&aacute;ch định nghĩa một giao diện chức năng trong Java như sau.</p> <pre class="language-java"><code>import java.lang.FunctionalInterface; @FunctionalInterface public interface MyInterface{ double getValue(); }</code></pre> <p>Trong v&iacute; dụ tr&ecirc;n, giao diện MyInterface chỉ c&oacute; một phương thức trừu tượng l&agrave; getValue(). Do đ&oacute;, n&oacute; l&agrave; một giao diện chức năng. Ở đ&acirc;y, ch&uacute;ng ta đ&atilde; sử dụng ch&uacute; th&iacute;ch @FunctionInterface. Ch&uacute; th&iacute;ch sẽ buộc tr&igrave;nh bi&ecirc;n dịch Java chỉ ra rằng giao diện n&agrave;y l&agrave; một giao diện chức năng. Do đ&oacute;, kh&ocirc;ng cho ph&eacute;p c&oacute; nhiều hơn một phương thức trừu tượng. Tuy nhi&ecirc;n, điều n&agrave;y l&agrave; kh&ocirc;ng bắt buộc.</p> <p>Trong Java 7, c&aacute;c giao diện chức năng được coi l&agrave; c&aacute;c phương thức trừu tượng đơn hoặc kiểu SAM. SAM thường được triển khai với lớp ẩn danh trong Java 7.</p> <h2>Giới thiệu về biểu thức Lambda</h2> <p>Về cơ bản, biểu thức Lambda l&agrave; một phương thức ẩn danh hoặc kh&ocirc;ng được đặt t&ecirc;n. Biểu thức lambda kh&ocirc;ng tự thực thi. Thay v&agrave;o đ&oacute;, n&oacute; được sử dụng để triển khai một phương thức được x&aacute;c định bởi một giao diện chức năng.</p> <p>L&agrave;m thế n&agrave;o để định nghĩa một biểu thức Lambda trong Java? Sau đ&acirc;y l&agrave; c&aacute;ch ch&uacute;ng ta c&oacute; thể định nghĩa biểu thức Lambda trong Java.</p> <pre class="language-markup"><code>(Danh s&aacute;ch tham số) -&gt; Th&acirc;n Lambda</code></pre> <p>To&aacute;n tử (&rarr;) được gọi l&agrave; to&aacute;n tử Lambda. Giả sử, ch&uacute;ng ta c&oacute; một phương thức như sau:</p> <pre class="language-java"><code>double gia_tri() { return 4.56; }</code></pre> <p>Ch&uacute;ng ta c&oacute; thể viết phương thức n&agrave;y bằng c&aacute;ch sử dụng biểu thức Lambda như sau:</p> <pre class="language-java"><code>() -&gt; 4.56</code></pre> <p>Ở đ&acirc;y, phương thức kh&ocirc;ng c&oacute; bất kỳ tham số n&agrave;o. Do đ&oacute;, ph&iacute;a b&ecirc;n tr&aacute;i của to&aacute;n tử bao gồm danh s&aacute;ch c&aacute;c tham số trống rỗng. Ph&iacute;a b&ecirc;n phải l&agrave; phần th&acirc;n của biểu thức Lambda x&aacute;c định một h&agrave;nh động của biểu thức Lambda. Trong trường hợp n&agrave;y, n&oacute; sẽ trả về gi&aacute; trị 4.56.</p> <h2>C&aacute;c kiểu phần th&acirc;n của Lambda</h2> <p>Trong Java, th&acirc;n Lambda c&oacute; hai loại.</p> <ol> <li>Phần th&acirc;n chứa một biểu thức duy nhất.</li> </ol> <pre class="language-java"><code>()-&gt;System.out.println("Xin chao!");</code></pre> <ol start="2"> <li>Phần th&acirc;n chứa một khối đoạn m&atilde;.</li> </ol> <pre class="language-java"><code>()-&gt;{ double a = 4.56; return a; };</code></pre> <p>Loại phần th&acirc;n của Lambda n&agrave;y được gọi l&agrave; ph&acirc;n th&acirc;n chứa khối m&atilde;. Phần th&acirc;n n&agrave;y cho ph&eacute;p bao gồm nhiều c&acirc;u lệnh kh&aacute;c nhau. Những c&acirc;u lệnh n&agrave;y được đặt b&ecirc;n trong dấu ngoặc nhọn v&agrave; ta phải th&ecirc;m dấu chấm phẩy sau dấu ngoặc nhọn.</p> <p><strong>Ch&uacute; &yacute;: Đối với phần th&acirc;n chứa khối m&atilde;, ta c&oacute; thể c&oacute; c&acirc;u lệnh return nếu phần th&acirc;n trả về một gi&aacute; trị nhất định. Tuy nhi&ecirc;n, phần th&acirc;n kiểu n&agrave;y sẽ kh&ocirc;ng bắt buộc phải c&oacute; c&acirc;u lệnh return.</strong></p> <p>V&iacute; dụ: Ta sẽ viết một chương tr&igrave;nh Java trả về gi&aacute; trị bằng c&aacute;ch sử dụng biểu thức Lambda.</p> <p>Một biểu thức Lambda kh&ocirc;ng được thực thi ri&ecirc;ng biệt. M&agrave; n&oacute; tạo ra việc triển khai phương thức trừu tượng được định nghĩa bởi giao diện chức năng. V&igrave; vậy, trước ti&ecirc;n ch&uacute;ng ta cần định nghĩa một giao diện chức năng.</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>import java.lang.FunctionalInterface; @FunctionalInterface interface interface_1{ double gia_tri(); } public class Main { public static void main( String[] args ) { interface_1 a; a = () -&gt; 4.55; System.out.println(a.gia_tri()); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>4.55</code></pre> <p>Trong v&iacute; dụ tr&ecirc;n, ch&uacute;ng ta đ&atilde; tạo một giao diện chức năng c&oacute; t&ecirc;n l&agrave; interface_1. N&oacute; chứa một phương thức trừu tượng duy nhất c&oacute; t&ecirc;n gia_tri(). B&ecirc;n trong lớp Main, ch&uacute;ng ta đ&atilde; khai b&aacute;o một tham chiếu a đến interface_1. Lưu &yacute; rằng ch&uacute;ng ta c&oacute; thể khai b&aacute;o một tham chiếu của một giao diện nhưng ch&uacute;ng ta kh&ocirc;ng thể khởi tạo một giao diện.</p> <pre class="language-java"><code>interface_1 a = new interface_1();</code></pre> <p>C&acirc;u lệnh b&ecirc;n tr&ecirc;n sẽ bị th&ocirc;ng b&aacute;o lỗi.</p> <pre class="language-java"><code>interface_1 a;</code></pre> <p>Tuy nhi&ecirc;n, c&acirc;u lệnh b&ecirc;n tr&ecirc;n n&agrave;y l&agrave; hợp lệ.</p> <p>Sau đ&oacute;, ch&uacute;ng ta đ&atilde; g&aacute;n một biểu thức Lambda cho tham chiếu.</p> <pre class="language-java"><code>a = () -&gt; 4.55;</code></pre> <p>Cuối c&ugrave;ng, ch&uacute;ng ta gọi phương thức gia_tri().</p> <pre class="language-java"><code>System.out.println(a.gia_tri());</code></pre> <h2>Biểu thức Lambda chứa c&aacute;c tham số</h2> <p>Cho đến b&acirc;y giờ ch&uacute;ng ta đ&atilde; tạo c&aacute;c biểu thức Lambda m&agrave; kh&ocirc;ng c&oacute; bất kỳ tham số n&agrave;o. Tuy nhi&ecirc;n, biểu thức Lambda cũng c&oacute; thể c&oacute; c&aacute;c tham số.</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>(a) &rarr; (a%8)==0</code></pre> <p>Ở đ&acirc;y, biến a b&ecirc;n trong dấu ngoặc đơn l&agrave; một tham số được truyền cho biểu thức Lambda. Phần th&acirc;n Lambda sẽ nhận tham số n&agrave;y v&agrave; kiểm tra xem n&oacute; c&oacute; chia hết cho 8 hay kh&ocirc;ng.</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>@FunctionalInterface interface interface_1 { int phep_chia(int a); } public class Main { public static void main( String[] args ) { interface_1 ref = (so_nguyen) -&gt; { int b = so_nguyen%8; return b; }; String c; System.out.println("Co chia het cho 8 hay khong?: " + (c = (ref.phep_chia(8) == 0) ? "Co" : "Khong")); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>Co chia het cho 8 hay khong?: Co</code></pre> <h2>Giao diện chức năng tổng qu&aacute;t</h2> <p>Cho đến b&acirc;y giờ ch&uacute;ng ta đ&atilde; sử dụng giao diện chức năng chỉ chấp nhận một loại kiểu dữ liệu.</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>@FunctionalInterface interface interface_1 { int phep_chia(int a); }</code></pre> <p>Giao diện chức năng tr&ecirc;n chỉ chấp nhận kiểu dữ liệu số nguy&ecirc;n v&agrave; trả về một gi&aacute; trị kiểu số nguy&ecirc;n. Tuy nhi&ecirc;n, ch&uacute;ng ta c&oacute; thể l&agrave;m cho giao diện chức năng n&agrave;y trở n&ecirc;n tổng qu&aacute;t với nhiều kiểu dữ liệu kh&aacute;c.</p> <p>V&iacute; dụ:</p> <pre class="language-java"><code>@FunctionalInterface interface interface_1&lt;T&gt; { T phep_chia(T a); } public class Main { public static void main( String[] args ) { interface_1&lt;Integer&gt; ref = (so_nguyen) -&gt; { int a = so_nguyen % 8; return a; }; String c; System.out.println("Co chia het cho 8 hay khong?: " + (c = (ref.phep_chia(9) == 0) ? "Co " : "Khong ") + "Vi phep chia du: " + ref.phep_chia(9)); interface_1&lt;Float&gt; ref2 = (so_thuc) -&gt; { float a = so_thuc % 11.2f; return a; }; System.out.println("Co chia het cho 11.2 hay khong?: " + (c = (ref2.phep_chia(11.2f) == 0) ? "Co" : "Khong")); } }</code></pre> <p>Kết quả:</p> <pre class="language-markup"><code>Co chia het cho 8 hay khong?: Khong Vi phep chia du: 1 Co chia het cho 11.2 hay khong?: Co</code></pre> <p>Trong v&iacute; dụ tr&ecirc;n, ch&uacute;ng ta đ&atilde; tạo một giao diện chức năng tổng qu&aacute;t c&oacute; t&ecirc;n l&agrave; interface_1. N&oacute; chứa một phương thức tổng qu&aacute;t c&oacute; t&ecirc;n l&agrave; phep_chia(). B&ecirc;n trong lớp Main:</p> <ul> <li>interface_1&lt;Integer&gt; ref: Tạo một tham chiếu đến giao diện. Giao diện sẽ thực hiện thao t&aacute;c tr&ecirc;n dữ liệu kiểu k&yacute; tự số nguy&ecirc;n int.</li> <li>interface_1&lt;Float&gt; ref2: Tạo một tham chiếu đến giao diện. Trong trường hợp n&agrave;y, giao diện sẽ thực hiện thao t&aacute;c tr&ecirc;n dữ liệu kiểu số thực Float.</li> </ul> <p>Tr&ecirc;n đ&acirc;y l&agrave; kh&aacute;i niệm v&agrave; v&iacute; dụ cơ bản về biểu thức Lambda trong Java. Hy vọng mọi người c&oacute; thể &aacute;p dụng v&agrave;o trong chương tr&igrave;nh của m&igrave;nh. Mọi người h&atilde;y tiếp tục theo d&otilde;i c&aacute;c b&agrave;i tiếp theo v&agrave; cập nhật c&aacute;c b&agrave;i mới nhất tr&ecirc;n <a href="http://tek4.vn">tek4</a> nh&eacute;!</p>