Skip to main content

Command Palette

Search for a command to run...

Bài 9: Best Practices và Performance Tuning

Published
7 min readView as Markdown

I. Giới Thiệu

Sử dụng các Collection Framework một cách hiệu quả không chỉ giúp cải thiện hiệu suất của ứng dụng mà còn giúp mã nguồn dễ đọc, dễ bảo trì hơn. Bài viết này sẽ hướng dẫn các best practices và cách tối ưu hóa hiệu suất khi làm việc với Collection Framework trong Java.

II. Best Practices Khi Sử Dụng Collection

  1. Chọn Collection Phù Hợp

    Việc chọn đúng loại collection là rất quan trọng để đảm bảo hiệu suất và tính đúng đắn của ứng dụng. Dưới đây là một số hướng dẫn cơ bản:

    • ArrayList vs. LinkedList: Sử dụng ArrayList khi cần truy cập ngẫu nhiên nhanh. Sử dụng LinkedList khi cần thêm/xóa phần tử thường xuyên ở đầu hoặc giữa danh sách.

    • HashMap vs. TreeMap: Sử dụng HashMap khi không cần thứ tự các phần tử. Sử dụng TreeMap khi cần duy trì thứ tự sắp xếp.

    • HashSet vs. TreeSet: Sử dụng HashSet khi không cần thứ tự các phần tử. Sử dụng TreeSet khi cần duy trì thứ tự sắp xếp.

  2. Khởi Tạo Kích Thước Ban Đầu

    Khởi tạo kích thước ban đầu phù hợp cho các collection như ArrayListHashMap có thể giúp giảm số lần mở rộng và cải thiện hiệu suất.

     List<String> list = new ArrayList<>(100); // Khởi tạo với kích thước ban đầu 100
     Map<String, Integer> map = new HashMap<>(50); // Khởi tạo với kích thước ban đầu 50
    
  3. Sử Dụng Generics

    Sử dụng generics để đảm bảo type-safety và tránh lỗi thời gian chạy.

     List<String> list = new ArrayList<>(); // Đảm bảo chỉ thêm chuỗi vào danh sách
     list.add("Hello");
     // list.add(123); // Lỗi biên dịch
    
  4. Sử Dụng Interface Thay Vì Implementation

    Sử dụng interface thay vì lớp triển khai để tăng tính linh hoạt và dễ bảo trì.

     List<String> list = new ArrayList<>(); // Khuyến nghị
     ArrayList<String> list = new ArrayList<>(); // Không khuyến nghị
    
  5. Tránh Sử Dụng Synchronized Collection

    Tránh sử dụng các collection đồng bộ hóa (Collections.synchronizedList, Collections.synchronizedMap) khi không cần thiết. Thay vào đó, sử dụng các concurrent collections như ConcurrentHashMap.

     Map<String, Integer> map = new ConcurrentHashMap<>();
    

III. Performance Tuning

  1. Sử Dụng Primitive Types Khi Có Thể

    Sử dụng các kiểu nguyên thủy (int, long,...) thay vì các kiểu đối tượng (Integer, Long,...) để tránh boxing/unboxing và cải thiện hiệu suất.

     List<Integer> list = new ArrayList<>();
     for (int i = 0; i < 1000; i++) {
         list.add(i); // Boxing mỗi lần thêm phần tử
     }
    
  2. Sử Dụng For-Each Thay Vì Iterator

    Sử dụng vòng lặp for-each thay vì iterator để làm mã nguồn ngắn gọn và dễ hiểu hơn.

     List<String> list = Arrays.asList("A", "B", "C");
     for (String item : list) {
         System.out.println(item);
     }
    
  3. Tránh Sử Dụng Collection.addAll() Khi Có Thể

    Tránh sử dụng Collection.addAll() với một lượng lớn phần tử. Thay vào đó, khởi tạo collection mới với các phần tử cần thiết.

     List<String> list1 = Arrays.asList("A", "B", "C");
     List<String> list2 = new ArrayList<>(list1); // Tốt hơn là sử dụng addAll()
    
  4. Sử Dụng Stream API

    Stream API cung cấp các phương thức hiệu quả để thao tác trên các collection một cách dễ dàng và tối ưu.

     List<String> list = Arrays.asList("a", "b", "c");
     List<String> upperList = list.stream()
         .map(String::toUpperCase)
         .collect(Collectors.toList());
    

IV. Ví Dụ Minh Họa Chi Tiết

  1. Chọn Collection Phù Hợp

    Mô tả: Sử dụng ArrayList để lưu trữ danh sách sản phẩm và HashMap để lưu trữ thông tin số lượng sản phẩm theo mã sản phẩm.

     import java.util.ArrayList;
     import java.util.HashMap;
     import java.util.List;
     import java.util.Map;
    
     public class ProductInventory {
         private List<String> products = new ArrayList<>();
         private Map<String, Integer> productQuantities = new HashMap<>();
    
         public void addProduct(String product, int quantity) {
             products.add(product);
             productQuantities.put(product, quantity);
         }
    
         public int getProductQuantity(String product) {
             return productQuantities.getOrDefault(product, 0);
         }
    
         public static void main(String[] args) {
             ProductInventory inventory = new ProductInventory();
             inventory.addProduct("Laptop", 50);
             inventory.addProduct("Smartphone", 100);
    
             System.out.println("Laptop quantity: " + inventory.getProductQuantity("Laptop")); // Output: Laptop quantity: 50
             System.out.println("Smartphone quantity: " + inventory.getProductQuantity("Smartphone")); // Output: Smartphone quantity: 100
         }
     }
    
  2. Khởi Tạo Kích Thước Ban Đầu

    Mô tả: Tạo ArrayListHashMap với kích thước ban đầu phù hợp.

     import java.util.ArrayList;
     import java.util.HashMap;
     import java.util.List;
     import java.util.Map;
    
     public class InitialCapacityExample {
         public static void main(String[] args) {
             List<String> list = new ArrayList<>(100); // Khởi tạo với kích thước ban đầu 100
             Map<String, Integer> map = new HashMap<>(50); // Khởi tạo với kích thước ban đầu 50
    
             list.add("A");
             map.put("Apple", 1);
    
             System.out.println("List: " + list); // Output: List: [A]
             System.out.println("Map: " + map); // Output: Map: {Apple=1}
         }
     }
    
  3. Sử Dụng Generics

    Mô tả: Sử dụng generics để đảm bảo type-safety.

     import java.util.ArrayList;
     import java.util.List;
    
     public class GenericsExample {
         public static void main(String[] args) {
             List<String> list = new ArrayList<>(); // Đảm bảo chỉ thêm chuỗi vào danh sách
             list.add("Hello");
             // list.add(123); // Lỗi biên dịch
    
             System.out.println(list); // Output: [Hello]
         }
     }
    
  4. Sử Dụng Stream API

    Mô tả: Sử dụng Stream API để lọc và ánh xạ các phần tử trong danh sách.

     import java.util.Arrays;
     import java.util.List;
     import java.util.stream.Collectors;
    
     public class StreamAPIExample {
         public static void main(String[] args) {
             List<String> list = Arrays.asList("apple", "banana", "cherry");
    
             List<String> upperList = list.stream()
                 .map(String::toUpperCase)
                 .collect(Collectors.toList());
    
             System.out.println("Upper List: " + upperList); // Output: [APPLE, BANANA, CHERRY]
         }
     }
    

V. Bài Tập Thực Hành

  1. Tạo chương trình Java sử dụng ArrayList để lưu trữ danh sách sinh viên và HashMap để lưu trữ điểm của sinh viên.

    • Yêu cầu: Sử dụng ArrayList để lưu trữ tên sinh viên và HashMap để lưu trữ điểm của sinh viên theo tên.

    • Ví dụ:

        import java.util.ArrayList;
        import java.util.HashMap;
        import java.util.List;
        import java.util.Map;
      
        public class StudentScores {
            private List<String> students = new ArrayList<>();
            private Map<String, Integer> scores = new HashMap<>();
      
            public void addStudent(String student, int score) {
                students.add(student);
                scores.put(student, score);
            }
      
            public int getScore(String student) {
                return scores.getOrDefault(student, 0);
            }
      
            public static void main(String[] args) {
                StudentScores studentScores = new StudentScores();
                studentScores.addStudent("Alice", 90);
                studentScores.addStudent("Bob", 85);
      
                System.out.println("Alice's score: " + studentScores.getScore("Alice")); // Output: Alice's score: 90
                System.out.println("Bob's score: " + studentScores.get
      

Score("Bob")); // Output: Bob's score: 85 } } ```

  1. Tạo chương trình Java sử dụng ConcurrentHashMap để quản lý số lượng sản phẩm trong kho.

    • Yêu cầu: Sử dụng ConcurrentHashMap để đảm bảo tính đồng bộ khi thêm và lấy thông tin sản phẩm.

    • Ví dụ:

        import java.util.concurrent.ConcurrentHashMap;
        import java.util.Map;
      
        public class Warehouse {
            private final Map<String, Integer> stock = new ConcurrentHashMap<>();
      
            public void addProduct(String product, int quantity) {
                stock.merge(product, quantity, Integer::sum);
            }
      
            public int getProductQuantity(String product) {
                return stock.getOrDefault(product, 0);
            }
      
            public static void main(String[] args) {
                Warehouse warehouse = new Warehouse();
                warehouse.addProduct("Laptop", 10);
                warehouse.addProduct("Smartphone", 5);
      
                System.out.println("Laptop quantity: " + warehouse.getProductQuantity("Laptop")); // Output: Laptop quantity: 10
                System.out.println("Smartphone quantity: " + warehouse.getProductQuantity("Smartphone")); // Output: Smartphone quantity: 5
            }
        }
      
  2. Tạo chương trình Java sử dụng Stream API để lọc danh sách các sản phẩm và ánh xạ để lấy tên sản phẩm.

    • Yêu cầu: Lọc danh sách các sản phẩm có giá lớn hơn 100 và ánh xạ để lấy tên sản phẩm.

    • Ví dụ:

        import java.util.Arrays;
        import java.util.List;
        import java.util.stream.Collectors;
      
        class Product {
            String name;
            double price;
      
            Product(String name, double price) {
                this.name = name;
                this.price = price;
            }
      
            public String getName() {
                return name;
            }
      
            public double getPrice() {
                return price;
            }
        }
      
        public class StreamFilterExample {
            public static void main(String[] args) {
                List<Product> products = Arrays.asList(
                    new Product("Laptop", 1200),
                    new Product("Smartphone", 800),
                    new Product("Tablet", 200),
                    new Product("Mouse", 50)
                );
      
                List<String> expensiveProductNames = products.stream()
                    .filter(product -> product.getPrice() > 100)
                    .map(Product::getName)
                    .collect(Collectors.toList());
      
                System.out.println("Expensive Products: " + expensiveProductNames); // Output: [Laptop, Smartphone, Tablet]
            }
        }
      
  3. Tạo chương trình Java sử dụng ArrayList để lưu trữ danh sách các số và tính tổng các số chẵn trong danh sách.

    • Yêu cầu: Sử dụng ArrayList để lưu trữ các số và tính tổng các số chẵn trong danh sách.

    • Ví dụ:

        import java.util.ArrayList;
        import java.util.List;
      
        public class EvenNumberSum {
            public static void main(String[] args) {
                List<Integer> numbers = new ArrayList<>();
                numbers.add(1);
                numbers.add(2);
                numbers.add(3);
                numbers.add(4);
                numbers.add(5);
      
                int sum = 0;
                for (int number : numbers) {
                    if (number % 2 == 0) {
                        sum += number;
                    }
                }
      
                System.out.println("Sum of even numbers: " + sum); // Output: Sum of even numbers: 6
            }
        }
      

VI. Kết Luận

Trong bài viết này, chúng ta đã khám phá các best practices và cách tối ưu hóa hiệu suất khi làm việc với Collection Framework trong Java. Hiểu rõ và áp dụng các best practices này sẽ giúp bạn xây dựng các ứng dụng hiệu quả và dễ bảo trì hơn. Các ví dụ minh họa và bài tập thực hành sẽ giúp củng cố kiến thức và ứng dụng hiệu quả trong các dự án thực tế.

VII. Tài Liệu Tham Khảo

  • Java SE Documentation: Java Collections Framework

  • "Effective Java" by Joshua Bloch: Các nguyên tắc và best practices khi sử dụng Collection Framework.

More from this blog

devngu

169 posts