Đề cập đến một vài vấn đề khi dùng for và string.

Vòng lặp.

Khi viết một vòng for hoặc một vòng while chúng ta thường lựa chọn cách thức duyệt theo chỉ số (index), chẳng hạn:

for(int i = 0; i < arr.length; i++){
     //thực thi các lệnh
  }

ngay cả khi chỉ số không được dùng gì trong for ngoài việc lấy lại giá trị từ vị trí đó của mảng hoặc collection. Nếu trong trường hợp vậy tôi sẽ dùng foreach như sau:

for(String a : arr){
     //thực thi các lệnh
  }

Một vấn đề nữa là khi duyệt một collection, có thể xảy ra tình trạng xóa element hoặc thêm mới, tức là dữ liệu trong collection đang duyệt ở loop bị thay đổi chẳng hạn:

List< String > list ...
  for(int i = 0; i < list.size(); i++){
     if(list.get(i).equals(“text”)) list.remove(i);
     else if(list.get(i).equals(“yahoo”)) list.add(“mail”);
  }

Điều này sẽ rất nguy hiển trong runtime, một lỗi thuộc về concurency, do vậy cài đặt trên là không thể, trong Java chúng ta có một cách thức viết khắc phục được lỗi này là :

List< String > list ...
  Iterator < String > iter = list.iterator();
  while(iter.hasNext()){
     String value = iter.next();
    if(value.equals(“text”)) iter.remove();
     else if(value.equals(“yahoo”)) list.add(“mail”);
  }

 String

Trong cài đặt, hầu như chúng ta sử dụng khá nhiều String, do đó, cũng có những vấn đề xảy ra với một lập trình viên thiếu kinh nghiệm, ta sẽ lần lượt xét một vài trường hợp dưới đây.

Một String có thể thay đổi dữ liệu, chẳng hạn bị xóa hoặc được thêm vào một vài phần tử, điển hình cộng string với nhau xảy ra khá nhiều, rất nhiều các tài liệu đều khuyến cáo nên dùng StringBuffer thay cho String trong trường hợp này nhằm cải thiện tốc độ thực thi, với một lượng phép toán lớn thì tốc độ sẽ được cải thiện trong thấy. Tuy nhiên các trình compiler hiện nay cũng rất thông minh, khi biên dịch, chúng sẽ phát hiện các đoạn code string+string rồi thay thế bằng StringBuffer với phép toán append. Trong Java 5, chúng ta lại thấy thêm một lớp nữa là StringBuilder , đây là một lớp làm việc giống như StringBuffer (thực chất là các dẫn xuất từ AbstractStringBuffer), điểm khác nhau giữa chúng là một cái có synchronized và một cái thì không. Nếu như một object không bị nhiều Thread truy cập và thay đổi dữ liệu, ta nên dùng StringBuilder để cải thiện tốc độ.

Một phép toán tôi thường gặp trong khi lập trình đó là phép kiểm tra một String object có rỗng hay không, thông thường ta hay dùng equals để kiểm tra, chẳng hạn str.equals(“”), điều này không sai nhưng sẽ nhanh hơn và thông minh hơn khi dùng hàm length() (lấy ra độ dài của string) để so sánh với 0, chẳng hạn str.length() == 0, Java 6 có cài đặt thêm hàm isEmpty() thực chất cũng là phép so sánh này. Một điểm nữa khi so sánh string với nhau là ta nên để ý các ký tự trắng ở hai đầu, có thể dùng hàm trim(), và mặc nhiên bỏ qua các ký tự hoa, dùng equalsIgnoreCase() để so sánh. Đừng bao giờ so sánh string theo kiểu string a == string b, đây là một phép so sánh địa chỉ bộ nhớ của một object, có thể dùng a.intern() == b.intern() thay thế nếu không muốn dùng equals.

Hàm startWith hay endWith cũng hay được sử dụng, tuy nhiên nếu string so sánh chỉ gồm một ký tự thì không nên dùng nó, chẳng hạn str.startWith(“a”), khi đó dùng charAt để thay thế, chẳng hạn str.charAt(0) == ‘a’, tương tự với hàm endWith. Hàm indexOf cũng vậy, nếu đối số truyền vào chỉ là một ký tự chẳng hạn str.indexOf(“,”) thì nên dùng str.indexOf(‘,’) thay thế.

Ở phần sau, tôi sẽ trình bày về những sở thích trong việc vận dụng Collection Framework khi viết code.