Vòng lặp
Vòng lặp là một một trong những cấu trúc lệnh của lập trình java mà chúng ta được tiếp xúc ngay từ đầu.
Để sử dụng vòng lặp thì rất đơn giản, thế nhưng các bạn có bao giờ hỏi mình sử dụng vòng lặp như thế là đúng hay chưa?
Các bạn xem ví dụ dưới đây
Vấn đề: Cho mảng số nguyên, in tất cả các phần tử của mảng ra console.
Bad code
public class Main { public static void main(String[] args) { int[] arr = {1,2,3,4,5,6,7,8,9}; for(int i = 0; i < arr.length; i++) System.out.print(arr[i] + " "); } }
Good code
public class Main { public static void main(String[] args) { int[] arr = {1,2,3,4,5,6,7,8,9}; for (int value : arr) System.out.print(value + " "); } }
Các bạn thấy ở cách 1 và cách 2 đều làm cùng một nhiệm vụ đó là in tất cả các phần tử của mảng ra màn hình console.
Thế nhưng với cách 1 chúng ta sử dụng for(int i = 0; i < arr.length; i++) biến i được khởi tạo và tăng biến đếm mà không được sử dụng cho mục đích nào.
Note: Trong trường hợp duyệt hoặc không quan tâm đến index của các phần tử trong mảng ta nên sử dụng cấu trúc for (int value : arr), còn nếu bạn cần sử dụng index của phần tử thì mới dùng cấu trúc trên nhé.
Rút trích dữ liệu
Cho một class Student
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; import java.util.List; @Getter @Setter @AllArgsConstructor public class Student { private String name; private boolean isMale; // true - male or false female private int age; private int score; private List<String> course; public void print() { System.out.println(this.name + " - " + (isMale ? "Male" : "Female") + " - "+ this.age + " - " + this.score); } }
Vấn đề: Lấy danh sách các sinh viên có điểm >=5 từ List<Student>
Bad code
List<Student> result = new ArrayList<>(); for (int i = 0; i < result.size(); i++) { if (students.get(i).getScore() >= 5) { result.add(students.get(i)); } }
Good code
List<Student> result = students.stream().filter( s -> s.getScore() >= 5).collect(Collectors.toList());
Note:
Hồi sinh viên mình đã từng rất vất vả khi cần rút trích, xoá, tìm kiếm trong các collection. If else từa lưa còn sai lui sai tới vì logic quá phức tạp, code dài ngoằn.
Thế nhưng mà một ngày nọ mình đã biết đến stream api và cách sử dụng của nó.
Thao tác với các collection giờ đây thật dễ dàng, chúng ra có thể trích xuất, delete, kiếm tra các tính chất của dữ liệu, Group by,… với stream api.
Câu điều kiện
Câu điều kiện cũng là một trong những cấu trúc lệnh chúng ta sử dụng hằng ngày để code, thế nhưng có vài tình huống chúng ta không để ý thì câu điều kiện trở thành một đoạn tấu hài đấy. Xem đây
Vấn đề: Mình cần viết hàm kiểm tra sinh viên có đậu hay rớt bằng cách nếu score >= 5 thì đậu ngược lại thì rớt.
Bad code
public static boolean isPass(int score) { if (score >= 5) return true; else return false; }
Good code
public static boolean isPass(int score) { return score >=5; }
Note: Đừng có if else gì hết =) kết quả của điều kiện là thứ chúng ta cần.
Vấn đề: Trả về true nếu học sinh là nam và có điểm >= 5
Bad code
public static boolean isMaleAndPass(Student student) { if (student.isMale()) { if (student.getScore() >= 5) return true; } return false; }
Good code
public static boolean isMaleAndPass(Student student) { return student.isMale() && student.getScore() >= 5; }
Note: Đôi lúc chúng ta cần hoà quyện vào nhau
Vấn đề: If else dài ngoằn
Bad code
if () ... else if... else if ... else
Good code
switch () { case 1: case 2: case n: default: }
Note: If else nhiều quá thì nên dùng switch – case nhé.
So sánh
public enum Level { LOW, MEDIUM, HIGH } public class Staff { private Level level; private String name; }
Vấn đề: Mình có class Level Staff như trên, bây giờ mình muốn so sánh Level của Staff.
Bad code
public class Main { public static void main(String[] args) { Staff staff = new Staff(null, "A"); System.out.println(staff.getLevel().equals(Level.HIGH)); } }
Ở trên mình new Staff với level bằng null, khi sử dụng equals nó sẽ báo NullPointerException.
Các bạn nên viết ngược lại như sau, lưu ý này chỉ áp dụng cho java. Ngôn ngữ khác mình hông chắc =).
Good code
System.out.println(Level.HIGH.equals(staff.getLevel()));
Exception
Khi catch nhiều exception cùng lúc bạn nên để exception theo mức độ detail
Staff staff = null; try { System.out.println(staff.getLevel()); } catch (Exception e) { System.out.println(); } catch (NullPointerException e) { e.printStackTrace(); }
Note: Như code ở trên bạn sẽ không bao giờ bắt được NullPointerException, vì catch sẽ chạy từ trên xuống dưới, nếu một catch nào bắt exception thì các catch ở phía sau sẽ dừng.
Ở trên Exception là lớp cha của NullPointerException nên nó sẽ bắt trước và chúng ta sẽ không bao giờ có được kết quả mong muốn. Tuy nhiên hiện nay nhiều IDE hỗ trợ cho mình chuyện này, nó sẽ báo lỗi nếu chúng ta đặt catch một exception lớp cha trước lớp con.
Vấn đề: Bỏ qua exception
try { // do something } catch (NumberFormatException e) { // skip }
Note: Đừng bao giờ bỏ qua một exception nào hết nhé. Ít nhất bạn cũng phải printStackTrace() để sau này lỗi còn biết đường sai chỗ nào, chứ bỏ qua là sau này không biết tìm chỗ nào luôn đó =).