Java Bài 11: Mảng (Array) – Yellow Code Books

Rate this item:

Rating: 4.9/5. From 35 votes.

Please wait…

Được chỉnh sửa ngày 10/11/2020.

Chào mừng các bạn đến với bài học Java số 11, bài học về Mảng. Bài học này nằm trong chuỗi bài học lập trình ngôn ngữ Java của Yellow Code Books.

Đầu tiên mình nói một chút về Mảng trước khi đi vào chi tiết. Có một số tài liệu hoặc chương trình học Java nói rất muộn về Mảng, thường thì họ dành để nói về lập trình hướng đối tượng (OOP) trước khi nói về Mảng. Theo mình nghĩ thì điều này hợp lý, vì trong Java, Mảng không phải là kiểu dữ liệu nguyên thủy. Mảng là một cấu trúc dữ liệu mới dựa trên các nền tảng của hướng đối tượng. Vì vậy, biết về hướng đối tượng rồi mới tới Mảng thì không sai tí nào.

Tuy nhiên để hiểu và sử dụng tốt Mảng trong Java, mình không nghĩ bạn phải cần một kiến thức sâu rộng về OOP. Vả lại Mảng rất hiệu quả, mà nếu sử dụng Mảng trễ quá về sau, mình e rằng bạn sẽ đánh mất một số cơ hội tốt để tiếp cận một số kiến thức thú vị của Java. Thêm nữa Mảng cũng có thể xem như nền tảng để tạo thành khái niệm Chuỗi (String) mà chúng ta cùng nói đến ở bài sau nữa, và String cũng là một khái niệm của OOP mà chúng ta cũng sẽ phải làm quen sớm.

Khái Niệm Mảng

Mảng, hay còn gọi là Array, là một cấu trúc dữ liệu, dùng để chứa một tập hợp các phần tử có kiểu dữ liệu tương tự nhau. Giả sử chúng ta có mảng các số nguyên, mảng này sẽ chứa tập hợp các phần tử có cùng kiểu dữ liệu là int. Ngoài tập hợp số nguyên như ví dụ vừa nêu, hay tập hợp các kiểu dữ liệu nguyên thủy mà bạn cũng dần được làm quen, Mảng còn chứa đựng tập hợp các dữ liệu “không nguyên thủy” mà chúng ta sẽ nói đến ở các bài sau nữa.

Khi bạn khai báo một Mảng, bạn phải chỉ định độ lớn cho nó, tức là chỉ định số phần tử tối đa mà Mảng đó có thể chứa. Mỗi một phần tử trong Mảng sẽ được quản lý theo Chỉ Số (Index), chỉ số sẽ bắt đầu bằng số 0 (bạn sẽ được làm quen với cách truy cập các phần tử Mảng dựa vào chỉ số ở các ví dụ phía dưới).

Giả sử mình đã tạo ra một Mảng có tối đa 10 phần tử kiểu int, khi lưu trữ mảng này vào bộ nhớ, chúng sẽ được sắp xếp gần nhau theo mô hình giả lập sau, mỗi ô là một phần tử kiểu int với các số trong đó là giá trị được lưu trữ vào.

Minh họa một mảng với 10 phần tửMinh họa một mảng với 10 phần tửMinh họa một mảng với 10 phần tử

Bạn đã rõ hơn về Mảng, vậy tại sao phải dùng cấu trúc này?

Tại Sao Phải Dùng Mảng?

Ý nghĩa của phần này muốn nói đến lợi ích của việc dùng Mảng.

Đúng như tên gọi và định nghĩa Mảng trên đây, cấu trúc dữ liệu Mảng sẽ giúp bạn lưu trữ danh sách các phần tử. Mình ví dụ như bạn sẽ cần lưu danh sách các sinh viên. Danh sách này sẽ được tổ chức sao cho bạn có thể truy xuất ngẫu nhiên nhanh chóng đến từng phần tử con. Chẳng hạn bạn muốn lấy thông tin sinh viên ở vị trí thứ 10. Pùm! Có ngay!. Danh sách này có thể được sắp xếp lại trật tự theo một tiêu chí nào đó, do đó bạn có thể nhanh chóng đọc ra top 10 sinh viên có điểm số cao nhất. Hay một lợi thế nữa của Mảng đó là với việc tổ chức các phần tử có kiểu dữ liệu tương tự nhau như vậy sẽ làm cho code của chúng ta tường minh và dễ quản lý hơn, giúp tối ưu code.

Tuy nhiên Mảng cũng có một bất lợi là bạn phải khai báo độ lớn, tức khai báo sẵn số lượng phần tử mà Mảng này sẽ sử dụng. Điều này làm code của bạn kém linh động vì có khi chúng ta muốn một mảng nhiều số lượng phần tử hơn, hoặc làm hiệu năng của hệ thống bị giảm do bạn khai báo sẵn một mảng với độ lớn quá cao mà không sử dụng hết số lượng vùng nhớ đã khai báo. Tất nhiên để khắc phục nhược điểm này của Mảng thì Java cũng có khái niệm ArrayList mà chúng ta sẽ làm quen ở một bài học khác.

Cách Sử Dụng Mảng

Cũng giống như khi bạn làm quen đến khái niệm biến, bạn phải biết cách khai báo, gán dữ liệu, sử dụng biến đó trong biểu thức. Với Mảng cũng vậy, nhưng bởi vì Mảng hơi đặc biệt là nó chứa đựng các phần tử con, cho nên ngoài những gì bạn có thể vận dùng từ việc sử dụng biến, sẽ có một vài cái mới ở đây mà bạn phải làm quen. Chúng ta cùng đi qua các bước trong việc sử dụng Mảng như sau nhé.

Khai Báo Mảng

Bạn có thể chọn một trong hai cách khai báo sau.

kiểu_dữ_liệu

[]

tên_mảng

;

hoặc

kiểu_dữ_liệu

tên_mảng

[]

;

Bạn nhớ là phải có cặp [ ] ở phần kiểu_dữ_liệu hoặc tên_mảng. Sở dĩ Java định nghĩa cả 2 cách khai báo như trên là vì cách thứ nhất là đúng chuẩn Java, trong khi cách thứ 2 thì Java hỗ trợ cách khai báo Mảng từ C/C++.

Cặp [ ] cũng thể hiện rằng đây là mảng, bạn có để ý thấy là nếu không có cặp ngoặc đó thì khai báo trên đây không khác gì việc khai báo một biến cả đúng không nào.

Uhm… Nhưng mà khác với biến ở chỗ Mảng ở bước khai báo này vẫn chưa sử dụng được, như đã nói, chúng ta cần chỉ định độ lớn của mảng, vấn đề này sẽ được nói ở mục sau.

Bây giờ là một ví dụ. Để khai báo một mảng các số nguyên, chúng ta code như sau.

int[] myArray;

Cấp Phát Bộ Nhớ Cho Mảng

Bạn phải dùng từ khóa new để cấp phát bộ nhớ cho Mảng. Lần trước bạn dùng đến new là ở Bài 7, khi đó bạn khởi tạo một biến scanner, bạn có nhớ không nào.

Dùng từ khóa new để khởi tạo một biến đối tượngDùng từ khóa new để khởi tạo một biến đối tượngDùng từ khóa new để khởi tạo một biến đối tượng

Với Mảng, việc cấp phát bộ nhớ cũng sẽ tương tự, như sau.

tên_mảng

=

new

kiểu_dữ_liệu

[

kích_cỡ_mảng

];

Ở bước này rất cần thiết phải có kích_cỡ_mảng, nếu không truyền vào tham số này, việc cấp phát sẽ phát sinh lỗi. Kích cỡ này là do bạn quyết định, thông thường trong một ứng dụng, nếu biết chính xác thông số kích cỡ này và kích cỡ này sẽ không bị thay đổi trong suốt quá trình sống của ứng dụng, thì bạn hãy sử dụng mảng, nếu không biết chính xác hoặc kích cỡ luôn luôn thay đổi thì chúng ta nên dùng đến ArrayList như bài học sau này sẽ nói đến.

Tiếp nối ví dụ khai báo ở trên kia, chúng ta thêm phần cấp phát như sau.

int[] myArray = new int[10];

Khi ứng dụng chạy đến bước này, nó sẽ tạo ra một mảng với 10 phần tử số nguyên “rỗng” như minh họa sau.

Minh họa một mảng với 10 phần tử chưa có giá trịMinh họa một mảng với 10 phần tử chưa có giá trịMinh họa một mảng với 10 phần tử chưa có giá trị

Khởi Tạo Mảng

Như bạn thấy, bước cấp phát trên đây chỉ như một thao tác giữ chỗ trong hệ thống một vùng nhớ đủ rộng để chứa 10 phần tử số nguyên. Việc kế tiếp để mảng hoạt động là khởi tạo, hay còn hiểu là chứa dữ liệu vào trong các ô trống đó.

Có nhiều cách khởi tạo giá trị cho mảng.

Cách Thứ Nhất

Khởi tạo ngay khi vừa cấp phát bộ nhớ cho mảng, khi đó bạn không cần dùng từ khóa new nữa, chỉ khai báo và khởi tạo trên một dòng như ví dụ dưới. Dùng cách này khi bạn đã biết trước mình cần khởi tạo một mảng như thế nào ngay từ ban đầu. Với ví dụ mảng kiểu int như trên kia mình sẽ khởi tạo mảng theo cách thứ nhất như sau.

int[] myArray = {3, 5, 7, 30, 10, 5, 8, 23, 0, -5};

Cách Thứ Hai

Khởi tạo từng giá trị cho mảng bằng cách truy xuất đến chúng dựa vào chỉ số và gán cho chúng giá trị. Cách này được sử dụng khi bạn không biết ban đầu nên khởi tạo mảng ra sao, nhưng sau đó, với logic của ứng dụng, bạn sẽ điền tuần tự từng phần tử theo chỉ số của nó.

int[] myArray = new int[10];
myArray[0] = 3;
myArray[1] = 5;
myArray[2] = 7;
myArray[3] = 30;
myArray[4] = 10;
myArray[5] = 5;
myArray[6] = 8;
myArray[7] = 23;
myArray[8] = 0;
myArray[9] = -5;

Cả 2 cách trên đây đều cho ra mảng trong hệ thống diễn đạt như sơ đồ sau.

blank-diagram-page-1-5blank-diagram-page-1-5Minh họa một mảng với 10 phần tử được gán giá trị

Cách Khác

Ngoài ra thì đôi khi bạn còn dùng cả vòng lặp để khởi tạo giá trị, dùng trong trường hợp các giá trị mảng giống nhau, hay theo một trật tự nào đó, mình ví dụ với khởi tạo như sau.

int arraySize = 10;
int[] myArray = new int[arraySize];
for (int i = 0; i < arraySize; i++) {
    myArray[i] = i;
}

Khi này mảng sẽ chứa danh sách các giá trị giống như vầy.

blank-diagram-page-1-6blank-diagram-page-1-6Minh họa một mảng với 10 phần tử được gán giá trị bằng vòng for

Truy Cập Mảng

Như bạn đã làm quen với những cách trên đây, chúng ta sẽ truy cập vào mảng dựa vào chỉ số. Bạn luôn phải nhớ rằng chỉ số đầu tiên (chỉ số thứ nhất) của phần tử mảng bắt đầu từ 0, và chỉ số của phần tử thứ n sẽ là n-1.

Ví dụ như bạn muốn in ra console giá trị phần tử cuối cùng trong mảng 10 phần tử trên đây.

int[] myArray = {3, 5, 7, 30, 10, 5, 8, 23, 0, -5};
System.out.println("Phan tu thu 10: " + myArray[9]);

Hay nếu bạn muốn in ra tất cả các giá trị phần tử trong mảng, cách tốt nhất là hãy dùng vòng for.

int[] myArray = {3, 5, 7, 30, 10, 5, 8, 23, 0, -5};
for (int i = 0; i < myArray.length; i++) {
    System.out.println("Phan tu thu " + i + ": " + myArray[i]);
}

Lưu ý là nếu bạn dùng myArray.length thì hệ thống sẽ trả ra cho bạn độ lớn của mảng, trong trường hợp của ví dụ này độ lớn là 10. Toán tử “.” trong biểu thức trên sẽ được nói rõ hơn ở mục OOP.

Một Số Thực Hành Với Mảng

Bài Thực Hành Số 1

Bạn hãy tạo MẢNG CÁC SỐ NGUYÊN và khởi tạo giá trị cho mảng như sau {3, 5, 7, 30, 10, 5, 8, 23, 0, -5}. Hãy in ra console TỔNG và TRUNG BÌNH CỘNG của các giá trị phần tử trong mảng.

Và đây là code của bài thực hành.

int[] myArray = { 3, 5, 7, 30, 10, 5, 8, 23, 0, -5 };
int sum = 0;
double avg;
int count = myArray.length;
for (int i = 0; i < count; i++) {
    sum += myArray[i];
}
avg = (double) sum / count;
System.out.println("Sum is " + sum);
System.out.println("Avegare is " + avg);

Bài Thực Hành Số 2

Với mảng các số nguyên như bài thực hành trên. Bạn hãy in ra VỊ TRÍ (thứ tự) của các phần tử nhỏ hơn hay bằng 0.

Và code của chương trình.

int[] myArray = { 3, 5, 7, 30, 10, 5, 8, 23, 0, -5 };
int count = myArray.length;
boolean isFound = false;
for(int i = 0; i < count; i++) {
    if (myArray[i] <= 0) {
        System.out.println("The position below or equal zero is: " + i);
        isFound = true;
    }
}
 
if (!isFound) {
    System.out.println("Can not found the position you need");
}

Bài Thực Hành Số 3

Cũng với mảng các số nguyên như bài thực hành trên. Giờ bạn hãy sắp xếp lại các phần thử mảng theo thứ tự TĂNG DẦN, sao cho khi in ra console nội dung sẽ như vầy “-5  0  3  5  5  7  8  10  23  30”.

Và code như sau.

int[] myArray = {3, 5, 7, 30, 10, 5, 8, 23, 0, -5};

for (int i = 0; i < myArray.length - 1; i++) {
	for (int j = i; j <= myArray.length - 1; j++) {
		if (myArray[i] > myArray[j]) {
			// Thao tác này đổi chỗ 2 giá trị ở 2 vị trí i, j của mảng
			int temp;
			temp = myArray[i];
			myArray[i] = myArray[j];
			myArray[j] = temp;
		}
	}
}

for (int i = 0; i < myArray.length; i++) {
	System.out.print(myArray[i] + " ");
}

Chúng ta lại cùng nhau đi qua một kiến thức mới nữa trong Java, kiến thức Mảng. Tuy vậy kiến thức Mảng đã nói ở bài hôm nay vẫn còn một tí tẹo nữa vẫn chưa nói đến vì bài viết cũng khá dài, và… dài quá thì bạn lười đọc lắm :). Nói vậy thôi chứ tổng cộng kiến thức của Mảng cũng không nhiều và khó đâu, bao nhiêu đây cũng đủ cho bạn thử nghiệm giải các bài toán trên mạng hay trên lớp rồi nhé. Phần sau chỉ nói thêm cách sử dụng foreach trên mảng. Và hơi đau đầu một tí đó là mảng nhiều chiều, các bạn cùng đón đọc nhé.

Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy ủng hộ blog bằng cách:
– Đánh giá 5 sao ở mỗi bài viết nếu thấy thích.
– Comment bên dưới mỗi bài viết nếu có thắc mắc.
– Để lại địa chỉ email của bạn ở thanh bên phải để nhận được thông báo sớm nhất khi có bài viết mới.
– Chia sẻ các bài viết của Yellow Code Books đến nhiều người khác.
– Ủng hộ blog theo hướng dẫn ở thanh bên phải để blog ngày càng phát triển hơn.

Bài Kế Tiếp

Như đã nói, bạn sẽ được làm quen với phần 2 của Mảng, đó là foreach trên mảng, và Mảng nhiều chiều.