Mảng hai chiều trong java. Mảng trong Java. Một chiều và đa chiều

  • Hướng dẫn

Tôi nghĩ rằng rất ít người chuẩn bị cho cuộc phỏng vấn đầu tiên khi ứng tuyển vào công việc đầu tiên với tư cách là một lập trình viên cấp dưới sẽ trả lời câu hỏi này theo hướng tiêu cực. Hoặc ít nhất là nghi ngờ câu trả lời tích cực. Tất nhiên, cấu trúc dữ liệu đơn giản như vậy có khả năng truy cập chỉ mục trực tiếp - không cần thủ thuật! Không, trong một số ngôn ngữ như JavaScript hoặc PHP, mảng tất nhiên được triển khai theo một cách rất thú vị và về cơ bản không chỉ là một mảng. Nhưng đây không phải là điều chúng ta đang nói đến mà là về cách triển khai mảng “truyền thống” dưới dạng một “mảnh bộ nhớ liên tục”. Trong trường hợp này, dựa trên các chỉ số và kích thước của một phần tử, địa chỉ được tính toán đơn giản và giá trị tương ứng được truy cập. Có gì khó khăn thế?
Hãy tìm ra nó. Ví dụ: trong Java. Yêu cầu người nộp đơn không nghi ngờ tạo một mảng số nguyên N x N. Người đó tự tin viết một cái gì đó như:
int g = int mới[n][n];
Tuyệt vời. Bây giờ chúng tôi yêu cầu bạn khởi tạo các phần tử mảng bằng một cái gì đó. Ít nhất là theo đơn vị, ít nhất là tổng của các chỉ số. Chúng tôi nhận được:
for(int i = 0; i< n; i++) { for(int j = 0; j < n; j++) { g[i][j] = i + j; } }
Họ thậm chí còn viết thường xuyên hơn
for(int i = 0; i< g.length; i++) { for(int j = 0; j < g[i].length; j++) { g[i][j] = i + j; } }
đó cũng là lý do để trò chuyện, nhưng bây giờ chúng ta đang nói về một điều khác. Chúng tôi đang cố gắng tìm hiểu những gì một người biết và xem anh ta nghĩ như thế nào. Do đó, chúng tôi thu hút sự chú ý của anh ấy đến thực tế là các giá trị được đặt đối xứng và yêu cầu anh ấy lưu lại các lần lặp vòng lặp. Tất nhiên, tại sao phải đi qua tất cả các giá trị chỉ số khi bạn chỉ có thể đi qua hình tam giác phía dưới? Đối tượng thường dễ dàng đồng ý và làm nổi bật đường chéo chính một cách khôn ngoan, cẩn thận viết những điều như:
for(int i = 0; i< n; i++) { g[i][i] = 2* i; for(int j = 0; j < i; j++) { g[j][i] = g[i][j] = i + j; } }
Thay vì g[i][i] = 2* i; thường được viết g[i][i] = i + i; hoặc g[i][i] = tôi<< 1; и это тоже повод поговорить. Но мы идем дальше и задаем ключевой вопрос: Chương trình sẽ chạy nhanh hơn bao nhiêu?. Lý do thông thường như sau: tính toán chỉ số ít hơn gần 2 lần; tính toán giá trị ít hơn gần 2 lần (tổng hợp); số lượng nhiệm vụ như nhau. Điều này có nghĩa là nhanh hơn 30 phần trăm. Nếu một người có nền tảng toán học tốt, thì bạn thậm chí có thể thấy chính xác số lượng thao tác đã lưu và đánh giá hợp lý hơn về hiệu quả của việc tối ưu hóa.
Bây giờ là lúc diễn ra đòn chính. Chúng tôi chạy cả hai phiên bản mã trên một số giá trị đủ lớn N(khoảng vài nghìn), ví dụ như thế này.

Mã kiểm soát thời gian

lớp A ( public static void main(String args) ( int n = 8000; int g = new int[n][n]; long st, en; // one st = System.nanoTime(); for(int i = 0;< n; i++) { for(int j = 0; j < n; j++) { g[i][j] = i + j; } } en = System.nanoTime(); System.out.println("\nOne time " + (en - st)/1000000.d + " msc"); // two st = System.nanoTime(); for(int i = 0; i < n; i++) { g[i][i] = i + i; for(int j = 0; j < i; j++) { g[j][i] = g[i][j] = i + j; } } en = System.nanoTime(); System.out.println("\nTwo time " + (en - st)/1000000.d + " msc"); } }


Chúng ta thấy gì? Phiên bản tối ưu hóa hoạt động chậm hơn 10-100 lần! Bây giờ là lúc quan sát phản ứng của ứng viên đối với vị trí này. Phản ứng với một tình huống căng thẳng bất thường (chính xác hơn là thông thường trong thực tế của nhà phát triển) sẽ là gì. Nếu khuôn mặt của bị cáo tỏ ra phấn khích và anh ta bắt đầu bấm nút, tạm thời quên mất sự tồn tại của bạn thì đây là một dấu hiệu tốt. Đến một mức độ nhất định. Bạn không muốn thuê một nhà nghiên cứu không quan tâm đến kết quả của dự án, phải không? Vậy thì đừng hỏi anh ấy câu hỏi "Tại sao?" Yêu cầu họ làm lại tùy chọn thứ hai để nó thực sự hoạt động nhanh hơn tùy chọn đầu tiên.
Bây giờ bạn có thể an tâm tiếp tục công việc kinh doanh của mình trong một thời gian. Trong nửa giờ, bạn sẽ có đủ tài liệu để đánh giá những phẩm chất cá nhân và nghề nghiệp cơ bản của người nộp đơn.
Nhân tiện, khi tôi mô tả ngắn gọn vấn đề này trên trang web làm việc của mình, nhận xét phổ biến nhất là “Đây là đường cong Java của bạn”. Tôi đang đăng mã trên Tuyệt vời và Miễn phí, đặc biệt dành cho họ. Và những chủ sở hữu vui vẻ của Pascal miễn phí cho Windows có thể xem qua

dưới tấm lướt gió

Thời gian chương trình; sử dụngWindows; var bắt đầu, kết thúc, res: int64; n, i, j: Số nguyên; g: Mảng số nguyên; bắt đầu n:= 10000; SetLength(g, n, n); QueryPerformanceFrequency(res); QueryPerformanceCounter(bắt đầu); for i:=1 to n-1 do for j:=1 to n-1 do g := i + j; QueryPerformanceCounter(kết thúc); writeln("Thời gian theo hàng:", (kết thúc - bắt đầu) / res, " giây"); QueryPerformanceCounter(bắt đầu); for i:=1 to n-1 do for j:=1 to n-1 do g := i + j; QueryPerformanceCounter(kết thúc); writeln("Thời gian tính bằng cols:", (kết thúc - bắt đầu) / res, " giây"); kết thúc.


Trong đoạn mã trên bằng Pascal, tôi đã loại bỏ các khía cạnh “khó hiểu” và chỉ để lại bản chất của vấn đề. Nếu điều này có thể được gọi là một vấn đề.
Chúng ta sẽ hỏi bị cáo những câu hỏi gì?
1. Tại sao nó hoạt động chậm hơn? Và chi tiết hơn...
2. Làm thế nào để khởi tạo nhanh hơn?

Nếu có nhu cầu tìm hiểu sâu hơn về cách triển khai Java, thì chúng tôi yêu cầu người nộp đơn quan sát thời gian thực hiện đối với các giá trị nhỏ N. Ví dụ: trên ideone.com với n=117, tùy chọn “tối ưu hóa” chậm bằng một nửa. Nhưng đối với giá trị tiếp theo n=118, nó nhanh hơn 100 (một trăm) lần so với giá trị không được tối ưu hóa! Đề nghị thử nghiệm trên máy cục bộ. Hãy để anh ấy chơi với các cài đặt.
Nhân tiện, mọi người có hiểu chuyện gì đang xảy ra không?

Một vài lời biện minh

Tôi muốn nói vài lời để biện minh cho phương pháp phỏng vấn tuyển dụng này. Có, tôi không kiểm tra kiến ​​thức về cú pháp ngôn ngữ và kiến ​​thức về cấu trúc dữ liệu. Có lẽ, trong một thị trường lao động văn minh, tất cả những điều này đều có tác dụng. Nhưng trong điều kiện chúng ta đang thiếu hụt hoàn toàn nhân sự có trình độ, cần phải đánh giá mức độ phù hợp lâu dài của người nộp đơn đối với công việc mà anh ta sẽ phải đối mặt. Những thứ kia. khả năng học hỏi, đột phá, hiểu biết, làm việc.
Điều này có tinh thần tương tự như cuộc “phỏng vấn” tuyển mộ lính lê dương ở La Mã cổ đại. Người chiến binh tương lai vô cùng sợ hãi và quan sát xem anh ta có đỏ mặt hay tái nhợt không. Nếu anh ta tái mặt, thì trong tình huống căng thẳng, máu sẽ chảy ra khỏi đầu người nộp đơn và anh ta dễ có phản ứng thụ động. Ví dụ như ngất xỉu. Nếu người nộp đơn đỏ mặt thì máu dồn lên đầu. Những thứ kia. anh ta có xu hướng hành động tích cực và lao vào đánh nhau. Điều này được coi là phù hợp.
Vâng, một điều cuối cùng. Tại sao tôi lại nói với mọi người về vấn đề này thay vì tiếp tục sử dụng nó trong các cuộc phỏng vấn? Chỉ là những ứng viên tiềm năng đã “học” được nhiệm vụ này và phải sử dụng những nhiệm vụ khác.
Trên thực tế, tôi chú ý đến hiệu ứng này một cách chính xác liên quan đến nhiệm vụ thực sự của việc xử lý hình ảnh. Tình huống có phần khó hiểu và tôi không hiểu ngay tại sao khung hình/giây của mình lại giảm nhiều như vậy sau khi tái cấu trúc. Nói chung chắc hẳn ai cũng có rất nhiều khoảnh khắc tuyệt vời như vậy.

Cho đến nay, phiên bản hàng đầu là bộ nhớ đệm của bộ xử lý là nguyên nhân. Những thứ kia. truy cập tuần tự trong tùy chọn đầu tiên hoạt động trong một hàm băm, được cập nhật khi di chuyển ra ngoài một ranh giới nhất định. Khi truy cập theo cột, hàm băm buộc phải cập nhật liên tục và việc này mất rất nhiều thời gian. Hãy kiểm tra phiên bản này ở dạng tinh khiết nhất của nó. Hãy tạo một mảng và so sánh cái nào nhanh hơn - xử lý tất cả các phần tử trong một hàng hay xử lý các phần tử mảng có số ngẫu nhiên với cùng số lần? Chương trình này là ideone.com/tMaR2S. Đối với 100.000 phần tử mảng, truy cập ngẫu nhiên thường nhanh hơn đáng kể. Điều đó có nghĩa là gì?
Ở đây, tôi (Big_Lebowski) đã chỉ ra khá đúng rằng việc sắp xếp lại các vòng lặp sẽ thay đổi kết quả theo hướng có lợi cho tùy chọn tuần tự. Để đảm bảo độ thuần khiết của thí nghiệm, tôi phải thiết lập một chu trình khởi động. Đồng thời, tôi thực hiện lặp lại nhiều lần để có thời gian hoạt động trung bình như lời khuyên của Leventov. Hóa ra như thế này ideone.com/yN1H4g. Những thứ kia. Truy cập ngẫu nhiên vào các phần tử của một mảng lớn chậm hơn ~ 10% so với truy cập tuần tự. Có lẽ bộ đệm thực sự có thể đóng một vai trò nào đó. Tuy nhiên, trong tình huống ban đầu, hiệu suất giảm đáng kể. Vì vậy, có một cái gì đó khác.

Dần dần, phiên bản về các hành động bổ sung khi di chuyển từ hàng này sang hàng khác đang trở thành người dẫn đầu. Và nó đúng. Vẫn còn phải tìm hiểu chính xác những gì đang xảy ra ở đó.

Thẻ: Thêm thẻ

19 câu trả lời

Bạn có thể sử dụng một khai báo mảng hoặc một hằng mảng (nhưng chỉ khi bạn khai báo ngay lập tức và tác động đến một biến; không thể sử dụng các hằng mảng để gán lại một mảng).

Đối với các loại nguyên thủy:

Int myIntArray = int mới; int myIntArray = (1,2,3); int myIntArray = new int(1,2,3);

Đối với các lớp như String thì giống nhau:

Chuỗi myStringArray = Chuỗi mới; Chuỗi myStringArray = ("a","b","c"); Chuỗi myStringArray = Chuỗi mới("a","b","c");

Phương pháp khởi tạo thứ ba rất hữu ích khi bạn khai báo một mảng lần đầu tiên rồi khởi tạo nó. Ở đây cần có một dàn diễn viên.

Chuỗi myStringArray; myStringArray = Chuỗi mới("a","b","c");

Có hai loại mảng.

Mảng một chiều

Cú pháp giá trị mặc định:

Int num = int mới;

Hoặc (ít được ưa thích hơn)

Int num = int mới;

Cú pháp với các giá trị được chỉ định (khởi tạo biến/trường):

Int num = (1,2,3,4,5);

Hoặc (ít được ưa thích hơn)

Int num = (1, 2, 3, 4, 5);

Ghi chú. Để thuận tiện, int num được ưa thích hơn vì nó nêu rõ rằng bạn đang nói về một mảng ở đây. Nếu không thì không có sự khác biệt. Không có gì.

Mảng đa chiều

Tuyên ngôn

int num = int mới;

Int num = int mới;

Int num = int mới;

Khởi tạo

số=1; số=2; số=1; số=2; số=1; số=2; số=1; số=2; số=1; số=2;

Int num=((1,2), (1,2), (1,2), (1,2), (1,2) );

Mảng Ragged (hoặc mảng không phải hình chữ nhật)

int num = int mới; num = int mới; num = int mới; num = int mới; num = int mới;

Vì vậy, ở đây chúng tôi xác định rõ ràng các cột.
Cách khác:

Int num=((1), (1,2), (1,2,3,4,5), (1,2), (1,2,3) );

Truy cập vào:

vì (int i=0; tôi<(num.length); i++) { for (int j=0;jNhư một sự thay thế:

For (int a: num) ( for (int i: a) ( System.out.println(i); ) )

Nhập tên biến = Loại mới; Nhập biếnName = (giá trị được phân cách bằng dấu phẩy); Nhập tên biến = Loại mới; Nhập biếnName = (giá trị được phân cách bằng dấu phẩy);

cũng hợp lệ, nhưng tôi thích dùng dấu ngoặc đơn sau kiểu này vì dễ thấy rằng kiểu của biến thực sự là một mảng.

Phần sau đây hiển thị một khai báo mảng, nhưng mảng không được khởi tạo:

Int myIntArray = int mới;

Dưới đây là phần khai báo cũng như khởi tạo mảng:

Int myIntArray = (1,2,3);

Bây giờ phần sau đây cũng hiển thị phần khai báo cũng như khởi tạo mảng:

Int myIntArray = new int(1,2,3);

Nhưng cái thứ ba này hiển thị thuộc tính tạo ẩn danh của một đối tượng mảng, được biểu thị bằng biến tham chiếu "myIntArray", vì vậy nếu chúng ta chỉ viết "new int(1,2,3);" thì nó có thể là một đối tượng mảng ẩn danh.

Nếu chúng ta chỉ viết:

Int myIntArray;

Đây không phải là một khai báo mảng, nhưng câu lệnh sau đây làm cho biểu thức sau hoàn chỉnh:

MyIntArray=int mới;

Tôi thấy nó hữu ích nếu bạn hiểu từng phần:

Tên loại = Loại mới;

Loại là loại biến được gọi là tên ("tên" được gọi là mã định danh). "Loại" theo nghĩa đen là loại cơ sở và dấu ngoặc đơn có nghĩa đó là loại mảng của cơ sở đó. Các kiểu mảng lần lượt là của riêng chúng, cho phép bạn tạo các mảng đa chiều thuộc loại Type ( kiểu mảng Type ). Từ khóa mới đề cập đến việc phân bổ bộ nhớ cho một mảng mới. Con số giữa dấu ngoặc cho biết mảng mới sẽ lớn đến mức nào và dung lượng bộ nhớ sẽ được phân bổ. Ví dụ: nếu Java biết rằng Loại cơ bản là 32 byte và bạn muốn một mảng có kích thước 5, thì nó cần phân bổ nội bộ 32 * 5 = 160 byte.

Bạn cũng có thể tạo mảng với các giá trị đã có sẵn, chẳng hạn như

Tên int = (1, 2, 3, 4, 5);

nó không chỉ tạo ra không gian trống mà còn lấp đầy nó bằng những giá trị này. Java có thể cho biết rằng các số nguyên gốc là các số nguyên và có 5 số nguyên trong số đó, do đó kích thước của mảng có thể được xác định ngầm.

Ngoài ra, nếu bạn muốn thứ gì đó năng động hơn, thì có giao diện Danh sách. Điều này sẽ không hoạt động, nhưng linh hoạt hơn:

Danh sách listOfString = danh sách mảng mới (); listOfString.add("foo"); listOfString.add("bar"); Giá trị chuỗi = listOfString.get(0); khẳng địnhEquals(giá trị, "foo");

Có hai cách chính để tạo một mảng:

Cái này, cho một mảng trống:

Mảng int = int mới[n]; // "n" là số khoảng trắng cần phân bổ trong mảng

Và cái này, cho một mảng được khởi tạo:

Mảng int = (1,2,3,4...);

Bạn cũng có thể tạo mảng nhiều chiều, ví dụ:

Int array2d = new int[x][y]; // "x" và "y" chỉ định kích thước int array2d = ( (1,2,3 ...), (4,5,6 ...) ...);

Lấy kiểu nguyên thủy int làm ví dụ. Có một số cách để khai báo một mảng int:

Int i = int mới; int i = int mới (value1, value2, value3, v.v); int i = (value1, value2, value3, v.v.);

trong tất cả các trường hợp này bạn có thể sử dụng int i thay vì int i .

Với sự phản chiếu, bạn có thể sử dụng (Type) Array.newInstance(Type.class, dung lượng);

Lưu ý rằng các tham số của phương thức... hiển thị các đối số có thể thay đổi. Về cơ bản thì số lượng tham số bao nhiêu cũng được. Giải thích bằng mã dễ dàng hơn:

Public static void varargs(int cố định1, Chuỗi cố định2, int... varargs) (...) ... varargs(0, "", 100); // cố định1 = 0, cố định2 = "", varargs = (100) varargs(0, "", 100, 200); // cố định1 = 0, cố định2 = "", varargs = (100, 200);

Bên trong phương thức, các varargs được xử lý như một int bình thường. Loại... chỉ có thể được sử dụng trong các tham số của phương thức, vì vậy int... i = new int() sẽ không biên dịch.

Lưu ý rằng khi truyền int cho một phương thức (hoặc bất kỳ Loại nào khác), bạn không thể sử dụng cách thứ ba. Trong câu lệnh int i = *(a, b, c, d, etc)*, trình biên dịch giả định rằng (...) có nghĩa là int . Nhưng đó là vì bạn đang khai báo một biến. Khi truyền một mảng cho một phương thức, khai báo phải là Loại mới hoặc Loại mới (...) .

Mảng đa chiều

Mảng đa chiều khó xử lý hơn nhiều. Về cơ bản, mảng 2D là một mảng gồm nhiều mảng. int có nghĩa là mảng int s. Điều quan trọng là nếu một int được khai báo là int[x][y] , thì chỉ số tối đa là i . Về cơ bản, một hình chữ nhật int bằng:

Khai báo một mảng tham chiếu đối tượng:

Lớp Animal () lớp Horse mở rộng Animal ( public static void main(String args) ( /* * Mảng Animal có thể chứa Animal và Horse (cho phép tất cả các kiểu con của Animal) */ Animal a1 = new Animal; a1 = new Animal() ; a1 = new Horse(); /* * Mảng Động vật và tất cả kiểu con của Ngựa */ Động vật a2 = Động vật mới(); của Ngựa chỉ có thể chứa Ngựa và kiểu con của nó (nếu có) và không được phép chứa siêu kiểu Ngựa cũng như loại khác kiểu con của Động vật */ Ngựa h1 = Ngựa mới; // Không được phép h1 = Ngựa mới(); * * Không thể khai báo điều này */ Ngựa h2 = Động vật mới;

Mảng là một danh sách tuần tự các phần tử

Mục int = giá trị; int one_directional_array = (giá trị, giá trị, giá trị, .., giá trị); int two_directional_array = ( ( value, value, value, .. value ), ( value, value, value, .. value ), .. .. .. .. ( value, value, value, .. value ) );

Nếu đây là một vật thể thì đây là khái niệm tương tự

Mục đối tượng = Đối tượng mới(); Đối tượng one_directional_array = ( new Object(), new Object(), .. new Object() ); Đối tượng two_directional_array = ( ( new Object(), new Object(), .. new Object() ), ( new Object(), new Object(), .. new Object() ), .. .. .. ( mới Object(), Object mới(), .. new Object() ) );

Trong trường hợp các đối tượng bạn cần gán nó thành null để khởi tạo bằng cách sử dụng new Type(..) , các lớp như String và Integer là những trường hợp đặc biệt sẽ được xử lý như sau

Chuỗi a = ("xin chào", "thế giới" ); // tương đương với Chuỗi a = ( new String(("h","e","l","l","o")), new String(("w","o","r" ,"l","d")) ); Số nguyên b = ( 1234, 5678 ); // tương đương với Integer b = ( new Integer(1234), new Integer(5678) );

Nói chung, bạn có thể tạo các mảng có M chiều

Int .. mảng = // ^ M lần ngoặc ((..( // ^ M lần ( ngoặc // đây là mảng.. // ^ M lần ))..) // ^ M lần ) ngoặc ;

Điều đáng chú ý là việc tạo mảng chiều M rất tốn kém về mặt không gian. Bởi vì khi bạn tạo một mảng M có N ở tất cả các chiều thì tổng kích thước của mảng lớn hơn N^M, vì mỗi mảng có một liên kết, và trong chiều M có một mảng chiều (M -1) của các liên kết. Kích thước tổng thể như sau

Mảng là một cấu trúc dữ liệu lưu trữ các giá trị cùng loại. Một phần tử mảng riêng lẻ được truy cập bằng chỉ mục số nguyên. Ví dụ: nếu a là một mảng các số nguyên thì giá trị của biểu thức a[i] bằng số nguyên thứ i trong mảng. Một mảng được khai báo như sau: đầu tiên, loại của mảng được chỉ định, tức là loại phần tử có trong mảng, theo sau là một cặp dấu ngoặc vuông trống và sau đó là tên của biến. Ví dụ: đây là cách khai báo một mảng gồm các số nguyên: int a; Tuy nhiên, câu lệnh này chỉ khai báo biến a mà không khởi tạo nó bằng một mảng thực tế. Để tạo một mảng, bạn cần sử dụng toán tử mới. int a = int mới [ 100 ] ; Toán tử này tạo ra một mảng gồm 100 số nguyên. Các phần tử của mảng này được đánh số từ 0 đến 99 (không phải từ 1 đến 100). Sau khi được tạo, mảng có thể được lấp đầy, chẳng hạn bằng cách sử dụng vòng lặp. int a = int mới [ 100 ] ; vì (int i = 0; tôi< 100 ; i++ ) a[ i] = i; // Điền vào mảng các số từ 0 đến 99 Nếu bạn cố gắng truy cập phần tử a (hoặc bất kỳ phần tử nào khác có chỉ mục nằm ngoài phạm vi từ 0 đến 99) bằng cách tạo một mảng gồm 100 phần tử, chương trình sẽ chấm dứt vì ngoại lệ chỉ số mảng nằm ngoài phạm vi giới hạn. Để đếm số phần tử trong một mảng, hãy sử dụng phương thức Arrayname.length. Ví dụ: với (int i = 0; i< a. length; i++ , System. out. println (a[ i] ) ) ; После создания массива изменить его размер невозможно (хотя можно, конечно, изменять отдельные его элементы). Если в ходе выполнения программы необходимо часто изменять размер массива, лучше использовать другую структуру данных, называемую списком массивов (array list). Массив можно объявить двумя способами: int a; или int a ; Большинство программистов на языке Java предпочитают первый стиль, поскольку в нем четче отделяется тип массива int (целочисленный массив) от имени переменной.

Bộ khởi tạo mảng và mảng không tên

Java có một phương tiện để đồng thời tạo và khởi tạo một mảng. Đây là một ví dụ về cấu trúc cú pháp như vậy: int SmallPrimes = (2, 3, 5, 7, 11, 13); Lưu ý rằng trong trường hợp này không cần sử dụng toán tử mới. Ngoài ra, bạn thậm chí có thể khởi tạo một mảng chưa được đặt tên: new int (16, 19, 23, 29, 31, 37) Biểu thức này phân bổ bộ nhớ cho một mảng mới và điền vào mảng đó các số được chỉ định trong dấu ngoặc nhọn. Trong trường hợp này, số lượng của chúng được tính toán và theo đó, kích thước của mảng được xác định. Cấu trúc cú pháp này rất thuận tiện khi sử dụng để khởi tạo lại một mảng mà không cần tạo biến mới. Ví dụ: biểu thức smallPrimes = new int (17, 19, 23, 29, 31, 37); là phiên bản viết tắt của biểu thức int ẩn danh = (17, 19, 23, 29, 31, 37); SmallPrimes = ẩn danh; Bạn có thể tạo một mảng có kích thước bằng không. Một mảng như vậy có thể hữu ích khi viết một phương thức đánh giá một mảng hóa ra trống. Một mảng có độ dài bằng 0 được khai báo như sau: Kiểu phần tử mới Lưu ý rằng mảng như vậy không tương đương với một đối tượng null.

Sao chép mảng

Một mảng có thể được sao chép sang mảng khác, nhưng cả hai biến sẽ tham chiếu đến cùng một mảng. int luckyNumbers = SmallPrimes; số may mắn[ 5] = 12 ; // Bây giờ phần tử SmallPrimes cũng là 12 Kết quả được hiển thị trong hình. 3.1. Nếu bạn cần sao chép tất cả các phần tử của mảng này sang mảng khác, bạn nên sử dụng phương thức arraycopy từ lớp System. Cuộc gọi của nó trông như thế này: System. bản sao mảng (từ, fromlndex, to, tolndex, count); Mảng to phải đủ lớn để chứa tất cả các phần tử cần sao chép. Hình.3.1. Sao chép một mảng Ví dụ: các toán tử được hiển thị bên dưới, kết quả của chúng được hiển thị trong Hình. 3.2, tạo hai mảng rồi sao chép bốn phần tử cuối cùng của mảng đầu tiên vào mảng thứ hai. Quá trình sao chép bắt đầu từ vị trí thứ hai trong mảng nguồn và các phần tử được sao chép được đặt trong mảng đích bắt đầu từ vị trí thứ ba. int SmallPrimes = (2, 3, 5, 7, 11, 13); int số may mắn = (1001, 1002, 1003, 1004, 1005, 1006, 1007); Hệ thống. công cụ thẩm định (smallPrimes, 2, luckyNumbers, 3, 4); vì (int i = 0; tôi< luckyNumbers. length; i++ ) System. out. println (i + ": " + luckyNumbers[ i] ) ; Выполнение этих операторов приводит к следующему результату. 0 : 1001 1 : 1002 2 : 1003 3 : 5 4 : 7 5 : 11 6 : 13 Cơm. 3.2. Sao chép các phần tử mảng Mảng trong Java khác biệt đáng kể so với mảng trong C++. Tuy nhiên, thực tế nó giống như một con trỏ tới một mảng động. Điều này có nghĩa là toán tử int a = new int [ 100 ] ; // Java tương đương với toán tử int * = new int [ 100 ] ; //C++, không phải int a[ 100 ] ; //C++ Trong ngôn ngữ Java, toán tử mặc định kiểm tra phạm vi thay đổi chỉ mục. Ngoài ra, Java không có con trỏ số học—bạn không thể tăng con trỏ để truy cập phần tử tiếp theo của mảng. Liên kết đến đầu tiên

Mảng là gì?

Mảng trong Java là tập hợp các phần tử cùng loại có thể được truy cập bằng chỉ mục.

Các phần tử mảng trong Java được đặt lần lượt trong bộ nhớ của máy tính. Dưới đây là một ví dụ về mảng trong Java.

Khai báo một mảng trong Java

Hãy khai báo một mảng để lưu trữ các phần tử kiểu int:

Ở đây biến arr được khai báo, là một mảng. Để sử dụng biến này, bạn cần xác định nó.

Định nghĩa mảng trong Java

Để xác định một mảng trong Java, bạn phải chỉ định độ dài của nó, tức là số phần tử có thể được lưu trữ trong đó:

Mảng của chúng ta sẽ lưu trữ 5 phần tử.

Mảng là một tập hợp các phần tử. Mỗi phần tử của mảng có thể được gọi bằng số của nó. Con số này thường được gọi là chỉ mục. Việc đánh số các phần tử mảng trong Java bắt đầu từ số 0.

Làm cách nào để tải các phần tử vào một mảng?

Hãy gán một giá trị cho phần tử đầu tiên của mảng và phần tử đầu tiên có chỉ số bằng 0:

Hãy gán một giá trị cho phần tử thứ hai của mảng và phần tử thứ hai có chỉ mục một:

for(int inn = 0; inn< 5; inn++)
{
Array = quán trọ;
}

Khi khai báo một mảng, bạn có thể nạp ngay các giá trị vào đó:

int mảng = (0, 1, 2, 3, 4);

số phần tử ở đây là 5, tức là Không cần chỉ định số lượng phần tử, nó sẽ được xác định tự động.

Làm thế nào để lấy các phần tử từ một mảng?

Mỗi phần tử của mảng có thể được gọi bằng số của nó. Để lấy một phần tử của mảng, bạn cần chỉ định tên mảng và chỉ mục của phần tử:

Đây là phần tử đầu tiên của mảng vì phần tử đầu tiên có chỉ số bằng 0.

Hãy gán giá trị của phần tử thứ ba của mảng cho biến int a:

Hãy xuất tất cả các phần tử của mảng trong một vòng lặp (chúng ta sẽ lặp lại mảng):

For(int inn = 0; inn< 5; inn++) { System.out.println("arr[" + inn + "] = " + arr); }

Một phiên bản đơn giản của vòng lặp để xuất ra một mảng như sau:

For(int inn: arr) ( System.out.println("arr[" + inn + "] = " + arr); )

Làm cách nào để xóa một mảng trong Java?

Bạn có thể xóa một mảng trong Java như thế này:

Làm cách nào để lấy độ dài của một mảng trong Java?

Chúng tôi nhận được độ dài của một mảng trong Java như thế này:

int arrLength = arr.length;

Làm cách nào để lấy phần tử đầu tiên của một mảng trong Java?

int firstElem = arr;

Làm cách nào để lấy phần tử nửa cuối của một mảng trong Java?

int LastElem = arr;

Làm cách nào để xác định một mảng có độ dài thay đổi trong Java?

Làm cách nào để xác định một mảng có độ dài thay đổi trong Java? Không đời nào. Khi bạn xác định một mảng, bạn sẽ đặt độ dài của nó; sau này bạn không thể thay đổi nó. Trong những trường hợp như vậy, các bộ sưu tập được sử dụng, ví dụ: Vector, ArrayList, v.v.

Vì vậy, độ dài mảng không thể thay đổi. Nhưng bạn có thể sử dụng một biến khi xác định một mảng. Nếu vậy:

int cd;
int ab = int mới;//Lỗi.

thì chúng tôi gặp lỗi: độ dài của mảng không thể là một biến.

Bạn cần đặt giá trị cd:

int cd = 10;
int ab = int mới;

Bây giờ thì ổn rồi. Nếu bạn thay đổi biến cd sau khi xác định mảng, điều này sẽ không ảnh hưởng đến mảng, tức là. chiều dài của nó sẽ không thay đổi. Ví dụ:

Int cd = 10; int ab = int mới; cd = 12;// Điều này có thể xảy ra arrLength = ab.length; System.out.println("ab array length = " + arrLength); //Kết quả: ab array length = 10 ab=4;// Và đây là lỗi

Chúng tôi gặp lỗi:

Ngoại lệ trong luồng "chính" java.lang.ArrayIndexOutOfBoundsException: 11

Chỉ số tối đa của mảng của chúng tôi là 9. Việc thay đổi giá trị của biến cd không ảnh hưởng đến mảng vì nó đã được xác định và độ dài của nó không đổi.

Các biến có thể được sử dụng để truy cập các phần tử mảng:

Int var = 1;
int elem = mảng;
var = 2;
elem = mảng;

Mảng ký tự trong Java

Một ví dụ về mảng ký tự trong Java và kết quả đầu ra của nó:

Char charArr = ("S", "B", "P"); for(int inn = 0; inn< charArr.length; inn++) { System.out.println("charArr[" + inn + "] = " + charArr); }

Làm cách nào để điền vào một mảng trong Java?

Bạn có thể điền vào một mảng bằng phương thức điền tĩnh.

Mảng là tập hợp các biến cùng loại được gọi bằng một tên chung. Mảng có thể được tạo từ các phần tử thuộc bất kỳ loại nào và chúng có thể có một hoặc nhiều chiều. Một phần tử cụ thể trong mảng được truy cập bằng chỉ mục (số) của nó. Trong lưu ý này, chúng ta sẽ xem xét việc xử lý mảng một chiều và hai chiều.

Mảng một chiều trong Java

Mảng một chiều về cơ bản là một danh sách các biến cùng loại. Để tạo một mảng, trước tiên bạn phải tạo một biến mảng có kiểu mong muốn. Cú pháp chung để khai báo mảng một chiều là:
gõ tên var;
Ở đây type khai báo kiểu cơ bản của mảng; var-name là tên của biến mảng. Kiểu cơ sở xác định kiểu dữ liệu của từng phần tử mảng. Ví dụ: khai báo mảng một chiều gồm các thành phần int có tên là tháng_days trông như sau:
int tháng_ngày ;
Mặc dù khai báo này chứng minh thực tế rằng tháng_ngày là một biến mảng nhưng thực tế không có mảng nào tồn tại. Trên thực tế, date_days được đặt thành null (con trỏ null), đại diện cho một mảng không có giá trị. Để liên kết tháng_ngày với một mảng số nguyên vật lý thực tế, bạn cần cấp phát bộ nhớ cho mảng đó bằng thao tác mới và gán nó cho mảng tháng_ngày; new là một hoạt động đặc biệt để phân bổ bộ nhớ.

Định dạng chung của new khi áp dụng cho mảng một chiều là:
mảng-var = kiểu mới;
trong đó kiểu là kiểu dữ liệu được phân phối, kích thước là số phần tử trong mảng, array-var là một biến được liên kết với mảng. Để sử dụng new để cấp phát bộ nhớ cho một mảng, bạn cần chỉ định loại và số lượng phần tử mảng. Các phần tử trong mảng được phân bổ bằng thao tác mới sẽ tự động được khởi tạo về 0. Ví dụ sau đây phân bổ bộ nhớ cho mảng số nguyên 12 phần tử và liên kết nó với biến tháng_ngày.
tháng_ngày = int mới;
Sau khi câu lệnh này được thực thi, tháng_days sẽ đề cập đến một mảng gồm 12 số nguyên. Khi đó tất cả các phần tử trong mảng sẽ được khởi tạo về 0.
Quá trình lấy một mảng bao gồm hai bước. Đầu tiên, bạn phải khai báo một biến mảng có kiểu mong muốn. Thứ hai, bạn cần phân bổ bộ nhớ sẽ chứa mảng bằng thao tác mới và gán nó cho một biến mảng. Do đó trong Java tất cả các mảng được phân bổ động.

Khi bạn đã cấp phát bộ nhớ cho một mảng, bạn có thể truy cập một phần tử cụ thể trong đó bằng cách chỉ định một chỉ mục trong dấu ngoặc vuông. Việc đánh số các phần tử mảng bắt đầu từ số 0. Tên mảng là tài liệu tham khảo.

Có thể kết hợp khai báo một biến mảng và cấp phát bộ nhớ cho mảng trực tiếp trong khai báo:
int tháng_ngày = int mới;

Hãy xem xét mã của một chương trình thay thế các phần tử âm của một mảng bằng phần tử lớn nhất:

Lớp công khai FindReplace ( public static void main(String args) ( int myArray; // khai báo không khởi tạo int mySecond = new int; /* cấp phát bộ nhớ với khởi tạo giá trị mặc định */ int a = (5, 10, 0, -5 , 16, -2); // khai báo có khởi tạo int max = a; for (int i = 0; i< a.length; i++) { if (a[i]<0) a[i] = max; mySecond[i] = a[i]; System.out.println("a[" + i + "]=" + a[i]); } myArray = a; // установка ссылки на массив a } }

Kết quả thực hiện sẽ là:

>java FindReplace a=5 a=10 a=0 a=5 a=16 a=5

Việc gán mySecond[i] = a[i] sẽ khiến một phần các phần tử của mảng mySecond, cụ thể là sáu, được gán giá trị của các phần tử của mảng a. Các phần tử còn lại của mySecond sẽ giữ lại các giá trị thu được trong quá trình khởi tạo, tức là các số 0. Nếu phép gán được tổ chức dưới dạng mySecond = a hoặc myArray = a thì cả hai mảng tham gia phép gán sẽ nhận được tham chiếu đến mảng a, nghĩa là cả hai sẽ chứa sáu phần tử và tham chiếu đến cùng một vị trí bộ nhớ.
Mảng có thể được khởi tạo tại thời điểm chúng được khai báo. Quá trình này rất giống với quá trình được sử dụng để khởi tạo các kiểu đơn giản. Trình khởi tạo mảng là danh sách các biểu thức được phân tách bằng dấu phẩy được bao quanh bởi dấu ngoặc nhọn. Mảng sẽ tự động được tạo đủ lớn để chứa bao nhiêu phần tử mà bạn chỉ định trong bộ khởi tạo mảng. Không cần phải sử dụng thao tác mới. Ví dụ: để lưu trữ số ngày trong mỗi tháng, đoạn mã sau tạo một mảng số nguyên được khởi tạo:

Lớp công khai ThángNgày ( public static void main(String args) ( int tháng_days = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31); System.out.println("April chứa " + tháng_ngày + " ngày."); ) )

Kết quả khi thực hiện chương trình, trên màn hình sẽ hiển thị như sau:

Tháng Tư có 30 ngày.

Bình luận: Java thực hiện kiểm tra nghiêm ngặt để đảm bảo bạn không vô tình cố lưu trữ hoặc đọc các giá trị bên ngoài vùng lưu trữ của mảng. Hệ thống điều hành Java cũng thực hiện kiểm tra cẩn thận để đảm bảo rằng tất cả các chỉ số mảng đều nằm trong phạm vi chính xác. (Về vấn đề này Java khác biệt đáng kể so với các ngôn ngữ C/C++, không cung cấp khả năng kiểm tra giới hạn thời gian chạy).

Mảng đa chiều trong Java

TRONG Mảng đa chiều Java trên thực tế là mảng của mảng. Chúng trông và hoạt động giống như các mảng đa chiều thông thường. Tuy nhiên, có một vài khác biệt tinh tế. Để khai báo một biến mảng nhiều chiều, hãy xác định từng chỉ mục bổ sung bằng cách sử dụng một bộ dấu ngoặc vuông khác nhau. Ví dụ: câu lệnh sau khai báo một biến mảng hai chiều có tên twoD:
int twoD = int mới;
Nó phân bổ bộ nhớ cho một mảng 4x5 và gán nó cho biến twoD. Trong nội bộ, ma trận này được triển khai dưới dạng một mảng gồm các số nguyên kiểu int.
Mảng đa chiều có thể được khởi tạo. Để thực hiện việc này, chỉ cần bao gồm trình khởi tạo của mỗi thứ nguyên trong bộ dấu ngoặc nhọn riêng của nó.
Chương trình sau đây tạo và khởi tạo các mảng có độ dài bằng nhau (ma trận) và thực hiện tích của ma trận này với ma trận khác:

Lớp công khai Ma trận ( private int a; Matrix(int ​​​​n, int m) ( // tạo và điền ngẫu nhiên a = new int[n][m]; for (int i = 0; i< n; ++i) for (int j = 0; j < m; ++j) a[i][j] = (int) (Math.random()*5); show(); } public Matrix(int n, int m, int k) { // создание и заполнение с random a = new int[n][m]; for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) a[i][j] = k; if (k != 0) show(); } public void show() { System.out.println("Матрица:" + a.length + " на " + a.length); for (int i = 0; i < a.length; ++i) { for (int j = 0; j < a.length; ++j) System.out.print(a[i][j] + " "); System.out.println(); } } public static void main(String args) { int n = 2, m = 3, z = 4; Matrix p = new Matrix(n, m); Matrix q = new Matrix(m, z); Matrix r = new Matrix(n, z, 0); for (int i = 0; i < p.a.length; ++i) for (int j = 0; j < q.a.length; ++j) for (int k = 0; k < p.a[i].length; ++k) r.a[i][j] += p.a[i][k]*q.a[k][j]; System.out.println("Произведение матриц: "); r.show(); } }

Vì các giá trị được gán cho các phần tử mảng bằng phương thức Random(), nên một trong các tùy chọn để thực thi mã có thể là như sau:

> javac Matrix.java > java Ma trận ma trận:2 x 3 3 2 0 3 3 1 Ma trận:3 x 4 1 2 2 3 3 2 3 2 1 2 3 2 Tích của ma trận: Ma trận:2 x 4 9 10 12 13 13 14 18 17

Ví dụ sau minh họa việc sao chép một mảng:

Lớp công khai ArrayCopyDemo ( public static void main(String args) ( int mas1 = (1,2,3), mas2 = (4,5,6,7,8,9); System.out.print("mas1: " ); show(mas1); System.out.print("mas2: "); // sao chép mảng mas1 sang mas2 System.arraycopy(mas1, 0, mas2, 2, 3); * 2 - phần tử bắt đầu thay thế * 3 - số phần tử được sao chép */ System.out.println("\n sau arraycopy(): "); ; show(mas1); System.out.print("\nmas2: "); riêng tư tĩnh void show(int mas) ( for (int i = 0; i< mas.length; ++i) System.out.print(" " + mas[i]); } }

Kết quả thực hiện chương trình:

> javac ArrayCopyDemo.java > java ArrayCopyDemo mas1: 1 2 3mas2: 4 5 6 7 8 9 sau arraycopy(): mas1: 1 2 3 mas2: 4 5 1 2 3 9

Cú pháp khai báo mảng thay thế

Có một dạng khác có thể được sử dụng để khai báo một mảng:
gõ tên var;
Ở đây dấu ngoặc vuông tuân theo bộ xác định loại chứ không phải tên biến mảng. Ví dụ: hai khai báo sau là tương đương:

Int al = int mới; int a2 = int mới;
Các khai báo được trình bày ở đây cũng tương đương với:
char twodi = char mới; char twod2 = char mới;
Hình thức thông báo thay thế này được đưa vào chủ yếu để thuận tiện.