[Tự học lập trình Java] Biến mảng

 

Mảng (Array)

Lập trình hướng đối tượng với Java - tinhoccoban.net

 Khái niệm.

Một mảng bao gồm các đối tượng có số lương cố định các giá trị của cùng một kiểu. Độ dài của một mảng được thành lập khi nó được tạo ra. Sau khi được tạo ra, độ dài đó là cố định. Ví dụ về mảng đã nói đến là trong hàm main của ứng dụng “Hello World”. Trong phần này sẽ thảo luận chi tiết hơn về mảng.

Mảng 10 phần tử trong Java -tinhoccoban.net
Một mảng có 10 phần tử.

Mỗi thành viên của mảng được gọi là một phần tử và mỗi phần tử được truy cập thông qua chỉ số mảng (index). Trong  minh họa ở trên chỉ số bắt đầu từ 0. Phần tử có thứ tự thứ 9 có chỉ mảng là 8.

Trong ví dụ ArrayDemo dưới đây, tạo ra mảng các số nguyên, đặt một vài giá trị vào trong mảng, và in mỗi giá trị đó theo hàm xuất chuẩn.

class ArrayDemo {
    public static void main(String[] args) {
        // Định nghĩa một mảng các số nguyên
        int[] anArray;
 
        // chỉ định mảng có 10 phần tử
        anArray = new int[10];
           
        // khởi gán phần tử đầu tiên của mảng
        anArray[0] = 100;
        // khởi gán phần tử thứ 2 của mảng
        anArray[1] = 200;
        // và các phần tử khác
        anArray[2] = 300;
        anArray[3] = 400;
        anArray[4] = 500;
        anArray[5] = 600;
        anArray[6] = 700;
        anArray[7] = 800;
        anArray[8] = 900;
        anArray[9] = 1000;
 
        System.out.println("Element at index 0: "
                           + anArray[0]);
        System.out.println("Element at index 1: "
                           + anArray[1]);
        System.out.println("Element at index 2: "
                           + anArray[2]);
        System.out.println("Element at index 3: "
                           + anArray[3]);
        System.out.println("Element at index 4: "
                           + anArray[4]);
        System.out.println("Element at index 5: "
                           + anArray[5]);
        System.out.println("Element at index 6: "
                           + anArray[6]);
        System.out.println("Element at index 7: "
                           + anArray[7]);
        System.out.println("Element at index 8: "
                           + anArray[8]);
        System.out.println("Element at index 9: "
                           + anArray[9]);
    }

Kết quả khi chạy chương trình như sau:

Element at index 0: 100
Element at index 1: 200
Element at index 2: 300
Element at index 3: 400
Element at index 4: 500
Element at index 5: 600
Element at index 6: 700
Element at index 7: 800
Element at index 8: 900
Element at index 9: 1000

Trong các tình huống lập trình thực tế, bạn cần sử dụng mảng với các cấu trúc lặp để duyệt các phần tử mảng. Ở đây, mỗi phần tử mảng thường được viết xử lý trên một dòng riêng như trong ví dụ. Tuy nhiên ví dụ này minh họa cú pháp truy cập phần tử một cách rõ ràng. Bạn sẽ được học về các cấu trúc lặp (for, while và do-while) trong phần cấu trúc điều khiển trong phần sau này.

Cú pháp khai báo mảng.

Trong chương trình có khai báo mảng trong mục trên (tên mảng là anArray) chúng ta thấy dòng code sau:

//Khai báo một mảng số nguyên

int[] anArray;

Giống như định nghĩa các của các kiểu biến khác, một biến mảng được định nghĩa bao gồm hai thành phần: Kiểu mảng và tên của mảng. Kiểu mảng được viết như type[], tại chữ type là kiểu dữ liệu của các phần tử chứa trong mảng; dấu ngoặc vuông là ký tự đặc biệt xác định đây là biến mảng. Kích thước mảng không được khai báo trong kiểu mảng (đó là lý do tại sao trong dấu ngoặc vuông lại là trống rỗng). Tên của mảng có thể là bất kỳ thứ gì mà bạn muốn, được tuân theo quy tắc đặt tên mà đã được bàn trong phần định danh ở mục trước. Cũng giống như các kiểu biến khác, việc khai báo không thực sự tạo ra một mảng; nó chỉ đơn giản là thông báo cho trình biên dịch biết biến này là biến mảng và có kiểu dữ liệu đi kèm.

Tương tự bạn có thể dịnh nghĩa các mảng với các kiểu dữ liệu khác như sau:

byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;

Bạn có thể thấy rằng các dấu ngoặc vuông được đặt phía trước các tên mảng.

// Hình thức khai báo này không được khuyến khích.
float anArrayOfFloats[];

Tuy nhiên quy ước không được khuyến khích đó, dấu ngoặc vuông xác định đây là kiểu mảng, xuất hiện với kiểu chỉ định.

Cách tạo mảng, khởi tạo mảng và truy cập một vào một mảng.

Một cách tạo ra một mảng là dùng toán tử new. Ví dụ dưới đây, lấy từ chương trình ArrayDemo, xác định một mảng với 10 phần tử số nguyên nằm trong một biến mảng.

// Tạo một mảng có các phần tử số nguyên
anArray = new int[10];

Với câu lệnh này là thiếu khi dùng mảng, chương trình sẽ in ra dòng thông báo lỗi như sau khi biên dịch

ArrayDemo.java:4: Variable anArray may not have been initialized.

Ý chỉ rằng biến mảng này chưa được khởi tạo. Chúng ta thêm vài dòng code gán các giá trị vào từng phần tử mảng như sau:

anArray[0] = 100; // initialize first element
anArray[1] = 200; // initialize second element
anArray[2] = 300; // and so forth

Mỗi phần tử mảng được truy cập thông qua chỉ số mảng:

System.out.println("Element 1 at index 0: " + anArray[0]);
System.out.println("Element 2 at index 1: " + anArray[1]);
System.out.println("Element 3 at index 2: " + anArray[2]);

Ngoài ra, bạn có thể sử dụng cú pháp tắt để tạo và khởi tạo mảng:

int[] anArray = { 
    100, 200, 300,
    400, 500, 600, 
    700, 800, 900, 1000
};

Ở đây kích thước của mảng được quyết định bởi những số nằm trong dấu ngoặc nhọn.

Bạn có thể định nghĩa một mảng của mảng (được biết đến với cái tên mảng đa chiều) được sử dụng 2 hoặc nhiều hơn dấu ngoặc vuông, như ví dụ String[][] names. Mỗi phần tử, vì thế phải được truy cập số tương ứng với các chỉ số.

Trong ngôn ngữ lập trình Java, một mảng đa chiều là một mảng mà các thành phần của chúng chính là các mảng. Điều này không giống trong ngôn ngữ lập trình C và ngôn ngữ lập trình Fortran. Một hệ quả tất yếu của việc này đó là các dòng cho phép thay đổi kích thước, giống như ví dụ MultiDimArrayDemo sau:

class MultiDimArrayDemo {
    public static void main(String[] args) {
        String[][] names = {
            {"Mr. ", "Mrs. ", "Ms. "},
            {"Smith", "Jones"}
        };
        // Mr. Smith
        System.out.println(names[0][0] + names[1][0]);
        // Ms. Jones
        System.out.println(names[0][2] + names[1][1]);
    }
}
Kết quả của chương trình trên là:

Mr. Smith
Ms. Jones

Cuối cùng, bạn cần sử dụng độ thuộc tính đô dài (length) xác định độ dài của mảng. Như đoạn mã nguồn sau:

System.out.println(anArray.length);

Copy mảng.

Trong lớp System, có một phương thức copy mảng arraycopy bạn có thể sử dụng để sao chép dữ liệu từ mảng này sang mảng khác.

public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)

Hai tham số Object trong mảng từ mảng đến mảng. Tham số thứ 3 là int là từ vị trí bắt đầu trong mảng nguồn, và vị trí bắt đầu trong mảng đích, và số lượng phần tử cần sao chép.

Trong chương trình ArrayCopyDemo dưới dây, định nghĩa một mảng có các phần tử kiểu chuỗi. Sử dụng phương thức System.arraycopy để chép ra một mảng con là mảng thứ 2.

class ArrayCopyDemo {
    public static void main(String[] args) {
        String[] copyFrom = {
            "Affogato", "Americano", "Cappuccino", "Corretto", "Cortado",   
            "Doppio", "Espresso", "Frappucino", "Freddo", "Lungo", "Macchiato",      
            "Marocchino", "Ristretto" };
        
        String[] copyTo = new String[7];
        System.arraycopy(copyFrom, 2, copyTo, 0, 7);
        for (String coffee : copyTo) {
            System.out.print(coffee + " ");           
        }
    }
}

Kết quả của chương trình là:

Cappuccino Corretto Cortado Doppio Espresso Frappucino Freddo 

Các thao tác mảng.

Sử dụng mảng là một sức mạnh trong lập trình. Java SE cung cấp các phương thức thực phổ biến nhất cho các thao tác liên quan đến mảng. Trong ví dụ ArrayCopyDemo ở trên sử dụng phương thức arraycopy trong lớp System để thay thế việc lặp giữa các phần tử trong mảng nguồn và các phần tử trong mảng đích. Điều này thực thi đằng sau, cho phép lập trình viên chỉ sử dụng một dòng code để gọi phương thức.

Để công việc lập trình của bạn tiện lợi, Java SE cung cấp các thao tác thực thi với mảng (các nhiệm vụ phổ biến, như sao chép, sắp xếp, tìm kiếm trong mảng) trong lớp  java.util.Arrays. Ví dụ, trong ví dụ trước có thể sửa thành sử dụng phương thức copyOfRange trong lớp java.util.Arrays để thay thế, xem trong ví dụ ArrayCopyOfDemo sau. Sự khác biệt ở đây là sử dụng phương thức copyOfRange không yêu cầu bạn phải tạo mảng đích trước khi gọi phương thức, bởi vì mảng đích được trả về bởi phương thức này.

class ArrayCopyOfDemo {
    public static void main(String[] args) {
        String[] copyFrom = {
            "Affogato", "Americano", "Cappuccino", "Corretto", "Cortado",   
            "Doppio", "Espresso", "Frappucino", "Freddo", "Lungo", "Macchiato",      
            "Marocchino", "Ristretto" };        
        String[] copyTo = java.util.Arrays.copyOfRange(copyFrom, 2, 9);        
        for (String coffee : copyTo) {
            System.out.print(coffee + " ");           
        }            
    }
}

Bạn có thể thấy rằng, đầu ra của chương trình là giống nhau, trong khi viết một vài dòng code. Tham số thứ hai của phương thức copyOfRange là chỉ số bắt đầu phạm vi sao chép, bao gồm tham số thứ ba là chỉ số kết thúc của phạm vi sao chép, không bao gồm phần tử này. Trong ví dụ này phạm vi được sao chép không bao gồm phần tử có chỉ số là 9 (chứa chuỗi Lungo). Một vài thao tác được cung cấp trong lớp java.util.Arrays là:

  • Tìm kiếm một giá trị và trả về chỉ số mảng.
  • So sánh 2 mảng.
  • Điền giá trị vào một mảng vào mỗi phẩn tử của mảng.
  • Sắp xếp một mảng theo chiều tăng dần. Điều này có thể được sử dụng một cách tuần tự, sử dụng phương thức sort hoặc sử dụng phương thức parallelSort trong Java SE 9. Sắp xếp song song cho các dãy số lớn trên hệ thống đa xử lý nhanh hơn phương thức sắp xếp mảng tuần tự.
  • Tạo một luồng có sử dụng một mảng là nguồn (phương thức stream). Ví dụ, câu lệnh in nội dung của mảng copyTo trong ví dụ trước có thể được làm như sau:
  • java.util.Arrays.stream(copyTo).map(coffee -> coffee + " ").forEach(System.out::print); 
  • Chuyển đổi mảng thành một chuỗi. Phương thức toString chuyển đổi mỗi phần tử mảng sang thành một chuỗi, phân cách giữa chúng là dấu phẩy, bao quanh chúng sẽ là dấu ngoặc vuông. Ví dụ, câu lệnh chuyển đổi mảng copyTo sang thành chuỗi và in chúng ra màn hình như sau:

System.out.println(java.util.Arrays.toString(copyTo)); 

Kết quả nhận được:

[Cappuccino, Corretto, Cortado, Doppio, Espresso, Frappucino, Freddo] 
Mới hơn Cũ hơn

Biểu mẫu liên hệ