Java Bài 12: Tiếp Tục Nói Về Mảng

Posted by

Được chỉnh sửa ngày 31/7/2017.

Chào mừng các bạn quay trở lại với Bài 12 trong chương trình học Java của Yellow Code Books.

Còn nhớ bài trước chúng ta cùng nói về khái niệm và cách thức sử dụng Mảng trong Java, khi đó mình cũng có nói đến cách thức hiệu quả nhất để duyệt qua các phần tử trong Mảng là dùng vòng lặp for. Hôm nay chúng ta tìm hiểu một “biến thể” khác của for dành riêng cho Mảng, giúp bạn có thể duyệt qua Mảng nhanh hơn những gì mà chúng ta cùng nói với nhau ở bài học về for và bài học về Mảng, đó gọi là foreach. Và còn một phần nâng cao của Mảng nữa cũng sẽ được nói đến ở bài hôm nay, đó là Mảng Nhiều Chiều.

foreach

Khái Niệm foreach Thông Qua Các Câu Hỏi

Câu hỏi đầu tiên: tại sao mình không nói về foreach ở bài học về for? Câu trả lời là, đúng là foreach cũng là for… vì nó là sự kết hợp giữa for và each… cú pháp của foreach cũng kế thừa từ for, và cách thức hoạt động của foreach dĩ nhiên cũng sẽ giống for rồi. Nhưng foreach lại sinh ra để làm việc chung với Mảng, foreach giúp thi triển các dòng code để duyệt trên mảng được dễ dàng hơn. Chính vì vậy mà foreach luôn được nói kèm với khái niệm về Mảng.

Câu hỏi tiếp theo là: foreach có quan trọng không? Câu trả lời là, không quan trọng nên sẽ không bắt buộc bạn phải dùng foreach đâu nhé. Như nói ở câu trả lời trên thì foreach chỉ giúp cho việc thi triển code trên vòng lặp được dễ dàng hơn thôi, bạn hoàn toàn có thể dùng for truyền thống để duyệt qua Mảng mà không cần đến foreach.

Cách Sử Dụng foreach

Trước hết chúng ta nói về cú pháp của foreach.

for (khai_báo_phần_tử_lặp : mảng) {
     các_câu_lệnh;
}

Bạn có thấy giống với for không nào. Với for bạn cần đưa vào 3 thành phần để định nghĩa các quy luật lặp cho nó. Còn với foreach, hiển nhiên vòng lặp này sẽ tự động biết nó phải đi qua lần lượt các phần tử trong mảng rồi, nên việc tham số cho vòng lặp này lại trở nên đơn giản hơn for nhiều. Mời bạn làm quen từng thành phần trong cú pháp foreach này.

khai_báo_các_phần_tử_lặp là nơi bạn sẽ khai báo một biến mới để dùng trong thân hàm foreach này. Biến này sẽ chứa đựng giá trị của phần tử mà vòng lặp này đang lặp đến, do đó nó phải có kiểu dữ liệu giống như kiểu dữ liệu của từng phần tử mảng.
mảng chính là Mảng bạn cần lặp. Đây có thể là một hàm trả về giá trị Mảng. Hàm, hay còn gọi là Phương thức, sẽ được nói đến ở bài học sau nhé.
Dấu hai chấm (:) được hiểu như là “trong”, vậy nghĩa cho tất cả các tham số trong foreach này là “từng phần tử trong mảng”.
các_câu_lệnh chính là nơi bạn dùng đến biến ở khai_báo_phần_tử_lặp ra dùng.

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

Chúng ta cùng làm lại bài thực hành số 1 ở bài Mảng hôm trước và thực hiện lại với foreach ở bài hôm nay. Mình copy lại nội dung bài thực hành hôm trước như sau.

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;
for (int i : myArray) {
	sum += i;
}
avg = (double) sum / myArray.length;
System.out.println("Sum is " + sum);
System.out.println("Avegare is " + avg);

Trường Hợp Nào Bạn Không Nên Dùng foreach?

Mặc dù foreach khá hay, mình cũng thích dùng nó, nhưng nên nhớ không phải lúc nào bạn cũng dùng foreach được đâu nhé, và sau đây là các trường hợp ngoại lệ đó.

– Không được dùng foreach để remove một phần tử nào đó khỏi Danh Sách (mình dùng từ “Danh Sách” chứ không phải “Mảng”, vì Mảng không cho phép bạn thêm hay bớt một phần tử trong nó, chỉ có Danh Sách mới cho phép, và vì foreach cũng sẽ làm việc trên Danh Sách tương tự như Mảng nên mình nhắc đến ý này ở đây, về sau khi nói đến Danh Sách mình sẽ nhắc lại cho bạn nhớ).
– Vì foreach tự duyệt tuần tự trên các phần tử mảng, nên nó rất dở trong việc xác định vị trí (chỉ số) của từng phần tử. Do đó đừng bắt foreach hoạt động khi bạn muốn truy xuất nhanh đến vị trí của bất kỳ phần tử nào đó.

Mảng Hai Chiều

Đến bước này chắc chắn bạn đã hiểu về khái niệm Mảng. Khi người ta nói tới Mảng, thì có nghĩa họ đang nói đến “Mảng một chiều”, như bạn biết thì Mảng này được xem như một danh sách (cố định) các phần tử trải dài theo một chiều duy nhất. Như minh họa bài trước thì Mảng (một chiều) nó như thế này.

blank-diagram-page-1-4

Bạn nghĩ sao nếu có một biểu diễn Mảng theo một chiều mới, khi này Mảng của bạn được gọi là Mảng hai chiều, mà người ta còn gọi là Ma Trận. Biểu diễn của Mảng hai chiều này trông như sau.

blank-diagram-page-1-1

Khai Báo Mảng Hai Chiều

Tương tự như khai báo Mảng, khai báo một Mảng hai chiều tương tự như vậy nhưng sẽ cần đến hai cặp ngoặc vuông [ ][ ].

kiểu_dữ_liệu[][] tên_mảng;

hoặc

kiểu_dữ_liệu tên_mảng[][];

Chúng ta thử khai báo Mảng hai chiều cho minh họa trên đây.

int[][] myMatrix;

Cấp Phát Bộ Nhớ Cho Mảng Hai Chiều

Cũng như Mảng. Cú pháp cấp phát cho Mảng hai chiều như sau.

tên_mảng = new kiểu_dữ_liệu[số_lượng_dòng][số_lượng_cột];

Vậy với ví dụ khai báo cho Mảng hai chiều ở trên, chúng ta tiến hình cấp phát như sau.

int[][] myMatrix = new int[4][5];

Khởi Tạo Mảng Hai Chiều

Lại cũng giống như Mảng, Mảng hai chiều cũng có nhiều hình thức khởi tạo. Giả sử mình muốn tạo ra một Mảng hai chiều với các giá trị như sau.

blank-diagram-page-1-2

Cách Thứ Nhất

Dùng khi bạn biết trước dữ liệu cần khởi tạo cho Mảng hai chiều, như là dữ liệu mình đưa ra trên đây, bạn khởi tạo như sau.

int[][] myMatrix = {
	{3, 5, 7, 30, 10},
	{5, 8, 23, 0, -5},
	{100, -9, 4, 2, 55},
	{-80, -22, 11, 1, 12}};

Cách Thứ Hai

Dùng cách này khi không biết dữ liệu ban đầu như thế nào, về sau tùy logic chương trình mà Mảng hai chiều sẽ được điền dữ liệu từ từ, khi đó bạn phải làm việc với chỉ số của nó. Một lưu ý là với Mảng hai chiều, chỉ số của nó được thể hiện như sau.

blank-diagram-page-1-3

Và để làm việc với chỉ số, thì bạn chú ý cách sử dụng chỉ số như khai báo sau nhé.

int[][] myMatrix = new int[4][5];

myMatrix[0][0] = 3;
myMatrix[0][1] = 5;
myMatrix[0][2] = 7;
myMatrix[0][3] = 30;
myMatrix[0][4] = 10;

myMatrix[1][0] = 5;
myMatrix[1][1] = 8;
myMatrix[1][2] = 23;
myMatrix[1][3] = 0;
myMatrix[1][4] = -5;

myMatrix[2][0] = 100;
myMatrix[2][1] = -9;
myMatrix[2][2] = 4;
myMatrix[2][3] = 2;
myMatrix[2][4] = 55;

myMatrix[3][0] = -80;
myMatrix[3][1] = -22;
myMatrix[3][2] = 11;
myMatrix[3][3] = 1;
myMatrix[3][4] = 12;

Cách Khác

Cũng giống như Mảng, Mảng hai chiều cũng có thể được khởi tạo bằng vòng lặp for, tất nhiên là bằng cách lồng hai for vào nhau rồi. Dùng cách này cho việc khởi tạo các giá trị cho Mảng hai chiều theo một trật tự nào đó. Bạn hãy xem ví dụ sau.

int row = 4;
int column = 5;
int[][] myMatrix = new int[row][column];

for (int i = 0; i < row; i++) {
	for (int j = 0; j < column; j++) {
		myMatrix[i][j] = i + j;
	}
}

Bạn có biết code trên đây sẽ tạo ra một Ma Trận như thế nào không. Ma Trận bạn tạo ra chính là hình minh họa bên dưới.

blank-diagram-page-1-4

Chắc chắn đến đây bạn đã hiểu rõ Mảng hai chiều hay Ma Trận rồi, tuy nhiên nếu có thắc mắc thì hãy để lại bình luận bên dưới bài học này cho mình nhé. Bây giờ chúng ta qua phần thực hành cho Ma Trận.

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

Bài này chúng ta sẽ thử thao tác với Ma Trận. Nhưng thay vì khai báo và khởi tạo sẵn một Ma Trận, bạn hãy thử nhập chúng từ console xem sao, sẽ rất thú vị đấy, nội dung của bài thực hành này như sau.

Tạo một Ma Trận các số nguyên bằng cách.

– In ra console dòng “Please enter number of row:” và đợi người dùng nhập vào số lượng hàng của Ma Trận.
– In ra console dòng “Please enter number of columns:” và đợi người dùng nhập vào số lượng cột của Ma Trận.
– In ra console từng dòng yêu cầu người dùng nhập từng phần tử của Ma Trận.

Với Ma Trận do người dùng nhập vào ở trên, thực hiện thao tác sau.

– In ra ma trận mà người dùng vừa mới nhập.
– In ra dòng và cột có tổng lớn nhất trong Ma Trận.

Nếu bạn đã hiểu yêu cầu bài thực hành thì tiến hành code nhé, code xong rồi thì mời bạn so sánh với kết quả của mình bên dưới. Hoan nghênh các bạn chia sẻ những suy nghĩ hoặc những giải thuật của bạn về bài thực hành này ở phần bên dưới bài học.

Đại loại của chương trình khi chạy, và khi tương tác với user sẽ như sau.

matrix

Và code như sau.

Scanner scanner = new Scanner(System.in);

// Nhập số lượng hàng
System.out.print("Please enter number of row: ");
int row = scanner.nextInt();

// Nhập số lượng cột
System.out.print("Please enter number of column: ");
int column = scanner.nextInt();

int[][] myMatrix = new int[row][column];

// Kêu user nhập vào từng phần tử của Ma Trận
for (int i = 0; i < row; i++) {
	for (int j = 0; j < column; j++) {
		System.out.print("Matrix[" + i + "][" + j + "] = ");
		myMatrix[i][j] = scanner.nextInt();
	}
}

// In ra ma trận user mới nhập
System.out.println("Your Matix here");
for (int i = 0; i < row; i++) {
	for (int j = 0; j < column; j++) {
		System.out.print(myMatrix[i][j] + "  ");
	}
	System.out.println(); // Đơn giản là xuống dòng
}

// Tìm dòng lớn nhất
int[] sumRow = new int[row]; // Mảng chứa tổng từng dòng
for (int ro = 0; ro < row; ro++) {
	for (int co = 0; co < column; co++) {
		sumRow[ro] += myMatrix[ro][co];
	}
}
int maxIndexRow = 0;
int maxSumRow = sumRow[maxIndexRow]; // Giả sử dòng 0 là dòng lớn nhất
for (int i = 1; i < row; i++) {
	if (maxSumRow < sumRow[i]) {
		maxSumRow = sumRow[i];
		maxIndexRow = i; // Lưu lại chỉ số dòng của số lớn nhất
	}
}
System.out.println("Max row in Matrix is row: " + maxIndexRow);

// Tìm cột lớn nhất
int[] sumColumn = new int[column]; // Mảng chứa tổng từng cột
for (int ro = 0; ro < row; ro++) {
	for (int co = 0; co < column; co++) {
		sumColumn[co] += myMatrix[ro][co];
	}
}
int maxIndexColumn = 0;
int maxSumColumn = sumColumn[maxIndexColumn]; // Giả sử cột 0 là dòng lớn nhất
for (int i = 1; i < column; i++) {
	if (maxSumColumn < sumColumn[i]) {
		maxSumColumn = sumColumn[i];
		maxIndexColumn = i; // Lưu lại chỉ số cột của số lớn nhất
	}
}
System.out.println("Max column in Matrix is column: " + maxIndexColumn);

Có Còn Thể Loại Mảng Nào Nữa?!!

Phần râu ria còn lại của bài học hôm nay mình xin gom hết vào đây, mình chỉ nói qua một lượt mà không có thực hành, cũng không cần các bạn phải hiểu rõ, vì phần này nói về các thể loại mảng còn lại trong Java mà hầu như chúng ta sẽ không dùng đến nó. Sự thật là mình chưa bao giờ dùng đến các thể loại mảng “cờ hó” này, nhưng biết đâu được ở đâu đó bạn sẽ chạm trán với nó, vậy thì hãy thử xem qua nó là gì nhé.

Mảng Ba Chiều

Vâng Mảng hai chiều đã đủ làm bạn chóng mặt, nay còn có cái thể loại Mảng ba chiều, thậm chí 4 chiều,… nhưng khoan khoan… bạn không cần phải dùng đến mảng nhiều chiều quá vậy đâu, hãy thử xem với mảng 3 chiều thì thao tác trên mảng sẽ như sau, đủ để bạn nản lòng rồi đấy.

int[][][] array3D = new int[4][5][3];
for (int row = 0; row < 4; row++) {
	for (int col = 0; col < 5; col++) {
		for (int ver = 0; ver < 3; ver++) {
			array3D[row][col][ver] = row + col + ver;
		}
	}
}

Mảng Răng Cưa

Ặc cái thể loại mảng này, mình cũng tránh xa. Cơ bản là mảng này được biểu diễn không “đều”, chẳng hạn như bạn có một Ma Trận có m dòng, mà mỗi dòng lại có số lượng cột khác nhau.

int[][] myJaggedArr = { { 3, 4, 5 }, { 77, 50 } };
for (int i = 0; i < myJaggedArr.length; i++) {
	for (int j = 0; j < myJaggedArr[i].length; j++) {
		System.out.print(myJaggedArr[i][j] + " ");
	}
	System.out.println();
}

Cuối cùng thì các kiến thức liên quan đến Mảng cũng đã xong, hi vọng các bạn có được một kiến thức vững và tốt để ứng dụng vào các bài học sau của Java, hoặc thực hiện xây dựng một ứng dụng Android của mình dựa trên nền tảng Java này.

Cảm ơn bạn đã đọc các bài viết của Yellow Code Books. Bạn hãy đánh giá 5 sao nếu thấy thích bài viết, hãy comment bên dưới nếu có thắc mắc, hãy để lại địa chỉ email của bạn để nhận được thông báo mới nhất khi có bài viết mới, và nhớ chia sẻ các bài viết của Yellow Code Books đến nhiều người khác nữa nhé.

Bài Kế Tiếp

Bài tiếp theo có kiến thức cũng liên quan đến Mảng, nhưng là Mảng các ký tự, người ta gọi là Chuỗi. Chuỗi có cấu tạo từ Mảng nhưng sẽ được Java ưu ái xây dựng cho Chuỗi các tính năng hấp dẫn, chúng ta cùng xem qua kiến thức về Chuỗi ở bài sau nhé.

Advertisements
Rating: 5.0. From 3 votes.
Please wait...

5 comments

  1. Bài Thực Hành Số 2 array [][] hình như code a sai sai cho này
    sumRow[r] += myMatrix[r][c]; // 34//
    sumColumn[c] += myMatrix[r][c];//51

    1. Wow code mình sai chắc! Thông thường thì mình code và kiểm tra qua trước rồi mới copy/paste vào bài học, nên không hiểu sao vẫn có sai sót chỗ này. Cảm ơn bạn đã chỉ ra chỗ sai nhé, mình sẽ sửa lại code của bài học.

    2. Mình hiểu rồi, do plugin của WordPress không chịu hiển thị nội dung “[c]“, nên những nơi có hiển thị kiểu đó sẽ bị xóa. Nên mình đã thay thế các biến r và c thành ro và co hết rồi. Hehe, dù sao cũng nhờ bạn phát hiện kịp thời, phải tìm plugin khác thôi.

Gửi phản hồi