1. Tổng quan về mảng
1.1. Khái niệm cơ bản
- Mảng (Array) là cấu trúc dữ liệu dùng để lưu trữ nhiều phần tử cùng kiểu.
- Các phần tử trong mảng được sắp xếp theo thứ tự và truy xuất thông qua chỉ số (index).
- Mảng là kiểu tham chiếu, kế thừa ngầm từ lớp
Object, do đó có thể gọi các phương thức củaObject. - Dữ liệu mảng được lưu trữ trong vùng nhớ heap.
1.2. Đặc điểm của mảng
- Các phần tử được lưu trữ liên tiếp và có thứ tự.
- Kích thước mảng không thay đổi sau khi khởi tạo.
- Phần tử mảng có thể là kiểu nguyên thủy hoặc tham chiếu.
- Mảng chiếm một khối nhớ liên tục; biến mảng lưu địa chỉ của phần tử đầu tiên.
- Truy cập phần tử qua chỉ số có độ phức tạp O(1).
1.3. Phân loại mảng
- Theo chiều: mảng một chiều, hai chiều, ba chiều, ...
- Theo kiểu phần tử:
- Mảng chứa kiểu nguyên thủy (
int,char,boolean, ...) - Mảng chứa đối tượng (lưu địa chỉ tham chiếu)
- Mảng chứa kiểu nguyên thủy (
- Theo cách khởi tạo: khởi tạo tĩnh và động.
1.4. Ưu và nhược điểm
- Ưu điểm: Truy xuất nhanh nhờ bộ nhớ liên tục và kích thước đồng nhất.
- Nhược điểm:
- Chèn/xóa chậm do phải dịch chuyển phần tử (độ phức tạp O(n)).
- Khó cấp phát khối nhớ lớn liên tục cho mảng rất lớn.
2. Mảng một chiều
2.1. Khai báo mảng
Cú pháp khuyến nghị:
kiểu_dữ_liệu[] tên_mảng;
Ví dụ:
int[] numbers;
double[] values;
String[] names;
Lưu ý: Không được khai báo kèm kích thước lúc khai báo, ví dụ int a[5]; là sai.
2.2. Khởi tạo mảng
a. Khởi tạo tĩnh
Gán giá trị ngay khi khởi tạo. Kích thước mảng bằng số phần tử được gán.
// Cách 1: Dùng new
int[] arr1 = new int[]{10, 20, 30};
// Cách 2: Viết tắt (chỉ dùng khi khai báo và gán cùng dòng)
int[] arr2 = {10, 20, 30};
Lưu ý: Không thể tách thành hai dòng với cú pháp viết tắt.
b. Khởi tạo động
Chỉ xác định kích thước, các phần tử mang giá trị mặc định.
int[] data = new int[5]; // Tạo mảng 5 phần tử, tất cả = 0
2.3. Thuộc tính và truy xuất phần tử
Mỗi mảng có thuộc tính length cho biết số phần tử.
int[] list = {1, 2, 3};
System.out.println(list.length); // In ra 3
Truy cập phần tử qua chỉ số bắt đầu từ 0:
int first = list[0]; // Lấy phần tử đầu tiên
list[0] = 100; // Gán lại giá trị
Chỉ số hợp lệ: từ 0 đến length - 1.
2.4. Duyệt mảng
a. Vòng lặp for truyền thống
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
b. Vòng lặp for cải tiến (enhanced for)
for (int value : arr) {
System.out.println(value);
}
Ưu điểm: ngắn gọn, dễ đọc. Nhược điểm: không có chỉ số.
2.5. Giá trị mặc định của phần tử
Khi khởi tạo động, phần tử mảng được gán giá trị mặc định tương tự biến thành viên:
byte,short,int,long:0float,double:0.0char:'\u0000'(ký tự null)boolean:false- Kiểu tham chiếu:
null
String[] words = new String[3];
System.out.println(words[0]); // In ra null
3. Phân tích bộ nhớ
Khi khai báo mảng:
- Biến mảng (tham chiếu) được lưu trong stack.
- Dữ liệu thực tế (các phần tử) được cấp phát trong heap.
Ví dụ:
int[] nums = new int[]{5, 10};
→ nums (trong stack) chứa địa chỉ trỏ đến khối nhớ trong heap chứa [5, 10].
3.1. Ví dụ ứng dụng
Ví dụ 1: Giải mã số điện thoại
public class DecodePhone {
public static void main(String[] args) {
int[] digits = {8, 2, 1, 0, 3};
int[] indices = {2, 0, 3, 2, 4, 0, 1, 3, 2, 3, 3};
StringBuilder phone = new StringBuilder();
for (int idx : indices) {
phone.append(digits[idx]);
}
System.out.println("Số điện thoại: " + phone);
}
}
Ví dụ 2: Chuyển số thành ngày trong tuần
import java.util.Scanner;
public class WeekdayConverter {
public static void main(String[] args) {
String[] weekdays = {"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday"};
Scanner input = new Scanner(System.in);
System.out.print("Nhập số (1-7): ");
int dayNum = input.nextInt();
if (dayNum >= 1 && dayNum <= 7) {
System.out.println("Ngày: " + weekdays[dayNum - 1]);
} else {
System.out.println("Số không hợp lệ.");
}
input.close();
}
}