آرایه چیست و کاربرد آن ها در جاوا
فرض کنید می خواهیم 100 عدد را ذخیره کنیم و با آن ها محاسبات انجام دهیم. با توجه به تعریف متغیر ها که در بخش های قبل خواندیم، باید 100 متغیر تعریف کنیم و هر عدد را در یکی از متغیر ها دخیره کنیم. یعنی برای کار با 100 عدد به 100 متغیر نیاز داریم.
در جاوا می توان 100 عدد (و هر مجموعه دیگری از مقادیر) را تحت یک نام ذخیره کرد. کلکسیون حاصل آرایه نام دارد. بنابراین
آرایه ، مجموعه ایی از مقادیر همنوع است که دارای یک نام می باشند. چون به عناصر آرایه از طریق اندیس مراجعه می شود ، آرایه را متغیر اندیس دار نیز می گویند.
مطالب و سر فصل هایی که در ادامه به بررسی آنها خواهیم پرداخت
- آرایه ها و نوع داده آنها
- آرایه های یک بعدی
- تعیین اندازه آرایه در حین اجرای برنامه
- مقدار دهی اولیه در زمان اعلان آرایه
- برگرداندن (بدست آوردن) اندازه آرایه
- چاپ مقادیر آرایه
- خطای (استثنای) خارج از حد آرایه و آدرس پایه
- ارسال آرایه به یک متد
- کپی کردن آرایه ای به آرایه دیگه
- آرایه ایی از اشیا
- آرایه دو بعدی
- کلاس Vector
- مثالی از کلاس Vector
آرایه ها و نوع داده آنها
همانطور که گفته شد ، آرایه ها مجموعه ایی از عناصر هم نوع هستند. عناصر موجود در آرایه ها می تواند
- int
- long
- double
- float
- char
- String
- اشیایی از کلاس ها
باشند.
برای مثال می تواند 100 عدد از نوع صحیح یا اعشاری را در یک آرایه با dataType صحیح نگهداری کرد یا آرایه ای از اشیای کلاس را ایجاد کرد.
اعلان آرایه های یک بعدی
در جاوا به یکی از دو صورت زیر که معادل یکدیگر هستند ، عمل می کنیم
dataType[] arrayName;
dataType arrayName[];
dataType همان نوع داده ایی است که آرایه در خودش ذخیره می کند ، که می تواند اشیای کلاس ، یا یک نوع داده اولیه باشد.
arrayName نام آرایه است.
مثال زیر را ببینید
int[] numbers;
int numbers[];
اعلان آرایه به معنی نمونه سازی شی آرایه (تخصیص حافظه برای آن) نیست. بعد از اعلان آرایه باید تخصیص حافظه برای آن صورت گیرد تا بتوانیم عنصری را وارد آرایه کنید. این کار توسط عملگر new انجام می شود.
مثال زیر تخصیص حافظه به آرایه ایی با نوع داده ایی صحیح به اندازه 50 مقدار صحیح است :
int[] numbers;
numbers = new int[50];
اعلان و تخصیص حافظه می تواند به دو صورت انجام شود :
حالت اول
int[] num, num2;
حالت دوم
int num[], num2;
تفاوت حالت اول و دوم چیست؟ از کدامیک استفاده کنیم؟
حالت اول می توانید در یک خط ، چندین آرایه اعلان کنید. اما در حالت دوم می توانید در یک خط از نوع داده اولیه int ، یک آرایه و یک متغیر را با هم اعلان کنید.
بنابراین بسته به نیاز خود می توانید به صورت دلخواه از هرکدام استفاده کنید.
تعیین اندازه آرایه در حین اجرای برنامه
می توان طول آرایه را یک فیلد در نظر بگیریم و در هنگام اجرای برنامه آن را از ورودی دریافت کنیم. دستورات زیر را ببینید
Scanner scnr = new Scanner(System.in);
int n;
int x[];
System.out.println("Enter the size of array: ");
n = scnr.nextInt();
x = new int[n];
مقدار دهی اولیه در زمان اعلان آرایه
در این حالت اندازه آرایه با تعداد مقادیر اولیه ای که به آرایه داده می شود ، مشخص می شود.
در مقدار دهی اولیه برای نمونه سازی شی از آرایه ، از عملگر new استفاده نمی کنیم.
دستورات زیر را ببینید
double[] numbers = {12.5, 13.75, 32.5, 23, 45.68};
هنگام اعلان آرایه و مقدار دهی اولیه به نکات زیر توجه کنید
- اندازه آرایه با توجه به تعداد عناصری که در آن قرار می دهیم مشخص می شود
- وقتی آرایه اعلان می شود و مقدار اولیه می گیرد ، برای نمونه سازی آن از عملگر new استفاده نمی کنیم. در این حالت نمونه سازی به صورت خودکار انجام می شود.
دسترسی به عناصر آرایه
بعد از اعلان و تخصیص حافظه و ورود عناصر به آرایه ، می توانیم با استفاده از اندیس (index) آرایه ، به عناصر موجود در آرایه دسترسی پیدا کنیم. دستور زیر را ببینید
arrayName[index];
اندیس آرایه که در بالا index نام دارد ، مقدارش نا منفی ، غیر صفر و یک واحد کمتر از طول آرایه است. برای مثال دستور زیر را در نظر داشته باشید
int[] n = {1,2,3,4,5,6,7};
تصویر آرایه n می تواند به صورت زیر نمایش داده شود
حالا برای دستیابی به هر عنصر باید شماره اندیس را برابر با شماره عنصر مورد نظر قرار دهیم. دستورات زیر را ببینید
System.out.println("n[0] -> " + n[0]);
System.out.println("n[1] -> " + n[1]);
System.out.println("n[2] -> " + n[2]);
System.out.println("n[3] -> " + n[3]);
System.out.println("n[4] -> " + n[4]);
System.out.println("n[5] -> " + n[5]);
System.out.println("n[6] -> " + n[6]);
خروجی دستورات به صورت زیر است
1
2
3
4
5
6
7
بنابراین مقدار اندیس ، موقعیت عنصر در آرایه را مشخص می کند
نکات زیر را در نظر داشته باشد
اندیس آرایه از 0 شروع می شود
عملگر [] را ، عملگر تعیین اندیس آرایه می نامند
همچنین می توانید عناصر موجود در آرایه را با استفاده از اندیس ، مقدار آنها را تغیر بدهید. برای مثال بالا ، آرایه n ، دستورات زیر را انجام می دهیم
n[0] = 15;
n[4] = 9;
عکس زیر تغیرات عناصر آرایه پس از انجام دستورات را نشان می دهد
برگرداندن (بدست آوردن) اندازه آرایه
هر آرایه را می توان با استفاده از نامش ، اندازه آن را برگرداند. دستور زیر آرایه ایی را ایجاد خواهد کرد
int[] n = new int[3];
تصویر آرایه ایجاد شده را می توان به شکل زیر نشان داد
حالا دستور زیر ، مقادیری از نوع صحیح را وارد خانه های آرایه می کند
n[0] = 10;
n[1] = 20;
n[3] = 30;
پس از اجرای دستورات بالا آرایه به صورت زیر در می آید
با توجه به اینکه آرایه یک شی است و با استفاده از عملگر new نمونه سازی می شود ، یک فیلد به نام length به صورت public final به همراه هر آرایه ایی نمونه سازی می شود. فیلد length حاوی اندازه آرایه است. چون دسترسی این فیلد public است می توان به صورت مستقیم به آن دسترسی داشت. دستور زیر اندازه آرایه n را چاپ می کند
System.out.println(n.length);
خروجی به صورت زیر است
3
چاپ مقادیر آرایه
با استفاده از یک حلقه for می توانیم مقادیر موجود در آرایه را چاپ کنیم
String[] names = {"Ali", "Reza", "Keyvan", "Sina", "Soheil"};
for(int i = 0; i < names.length; i++) {
System.out.println(names[i]);
}
خروجی دستورات بالا به صورت زیر می باشد
Ali
Reza
Keyvan
Sina
Soheil
حالا آرایه را از آخر به اول چاپ می کنیم
String[] names = {"Ali", "Reza", "Keyvan", "Sina", "Soheil"};
for(int i = names.length-1; i > 0; i--) {
System.out.println(names[i]);
}
خروجی به صورت زیر خواهد بود
Soheil
Sina
Keyvan
Reza
Ali
خطای (استثنای) خارج از حد آرایه و آدرس پایه
شما با استفاده از index به عنصر موجود در آرایه مراجعه می کنید. حالا اگر مقدار index از صفر کمتر یا از array.length-1 بیشتر باشد چه اتفاقی می افتد؟ این ایندکس ها را اندیس خارج از حد آرایه می گویند.
اگر ایندکس خارج از حد آرایه قرار دهیم ، منحر به صدور پیغام خطا خواهد شد. اصطلاحا می گوییم استثنای ArrayIndexOutOfBoundException رخ داده است
آدرس پایه (Base Address): به آدرس (مکان حافظه ای) اولین خانه یک آرایه ، آدرس پایه گفته می شود. در آرایه های یک بعدی آدرس پایه ، اولین عنصر آرایه است.
ارسال آرایه به یک متد
می توانیم هر یک از عناصر آرایه را به یک متد ارسال کنیم. همچنین می توانیم خود آرایه را به یک متد ارسال کنیم. با دو مثال این موضوع را شرح می دهیم.
ارسال یک عنصر از آرایه به متد
public void printArrayElement(int el) {
System.out.println(el);
}
int n[] = new int[3];
n[0] = 10;
n[1] = 20;
n[2] = 30;
printArrayElement(n[0]);
خروجی کد بالا به صورت زیر خواهد بود
10
ارسال یک آرایه به متد و چاپ تمامی عناصر آن
زمانی که آرایه ای را به عنوان پارامتر به متدی ارسال می کنیم ، آرایه را بدون [] در پارامتر قرار می دهیم
public void printArray(int arr) {
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
int n[] = new int[3];
n[0] = 10;
n[1] = 20;
n[2] = 30;
printArray(n);
نکته: آرایه ایی که به متد ارسال می شود مجازی است و تغیر در عناصر آرایه ، باعث تغیر در عناصر اصلی آرایه نمی شود.
خروجی کد بالا به صورت زیر خواهد بود
10
20
30
کپی کردن آرایه ایی به آرایه دیگر
بعد از اعلان و تخصیص حافظه آرایه شما دیگر نمی توانید اندازه آرایه را تغییر دهید یا عنصری از آن کم یا به آن اضافه کنید. بنابراین برای این کار باید آرایه مورد نظری را که می خواهید ، یک عنصر به آن اضافه یا کم کنید را در آرایه ایی جدید کپی کنید.
دستور زیر را ببینید
int[] x = {1,2,3,4,5};
int[] y = {6,7,8,9,10};
x = y;
با استفاده از x = y آرایه y را به آرایه x منتسب کردیم. یعنی به هر جایی که y اشاره می کند x هم به آنجا اشاره کند. بنابر این اگر مقادیر x و y را به خروجی ببریم به شکل زیر نمایش داده خواهد شد
x -> 6 7 8 9 10
y -> 6 7 8 9 10
محلی که قبلا x به آنجا اشاره می کرده به حافظه مازاد تبدیل می شود که زباله روب (Garbage) آن را جمع کرده و به سیستم تحویل می دهد.
با دستورات بالا دو آرایه به هم انتساب داده شدند که هر دو به یک مکان از حافظه بعد انتساب اشاره خواهند داشت. اما اگر بخواهیم مقادیر موجود در x به y کپی شود طوری که هم x و هم y به مکان های حافظه خودشان اشاره داشته باشند. باید از متد های موجود در جاوا که برای کپی کردن آرایه می باشد ، استفاده کنیم. با استفاده از متد arraycopy که یک متد static در کلاس System می باشد می توان آرایه ایی را در آرایه دیگر کپی کرد. دستور زیر نحوه استفاده از متد arraycopy را نشان می دهد. این نکته را به یاد داشته باشید که این یک متد قدیمی است. در ادامه از کلاس های Arrays و Vector خواهیم گفت و متد های این کلاس ها برای کار با آرایه ها را بررسی خواهیم کرد.
System.arraycopy(sourceArray, sourcePosition, destionationArray, destinationPosition, count);
این متد count عنصر از آرایه sourceArray با شروع از عنصری که با sourcePosition مشخص می شود ، در آرایه destinationArray با شروع از محل destinationPosition کپی می کند. دستورات زیر را ببینید
int[] sourceArray = {10,20,30,40,50};
int[] destinationArray = {60,70,80,90,100};
System.arraycopy(sourceArray, 0, destinationArray, 0, 2);
for(int i = 0; i < destinationArray.length; i++) {
System.out.println(destinationArray[i]);
}
دستورات بالا از عنصر 0 آرایه sourceArray شروع می کند و دو عنصر را بر می دارد (مقدار های 10 و 20) و از محل عنصر 0 آرایه destinationArray شروع به جایگذاری آن ها می کند (10 و 20 را جایگزین مقادیر 60 و 70 destionationArray میکند). بنابراین خروجی به صورت زیر است
10
20
80
90
100
در ادامه به بررسی کلاس های Vector و Arrays خواهیم پرداخت که امکانات بیشتری را در اختیار ما قرار خواهند داد.
آرایه ایی از اشیا
همانطور که تا کنون مشاهده کردید ، آرایه هایی که ایجاد کردیم با نوع داده اولیه بودند ، یعنی یک نوع تعریف شده در زبان برنامه نویسی جاوا مانند int و double و غیره. گاهی نیاز داریم آرایه ایی از اشیا داشته باشیم (برای مثال آرایه ای از دانش آموزان) .
برای این کار ابتدا یک کلاس به نام Student ایجاد می کنیم. با استفاده از سازنده (constructor) آن کلاس نام ، نام خانوادگی و معدل دانش آموز را میگیریم و به فیلد های مربوطه کلاس Student انتساب می دهیم. کد زیر برای کلاس Student می باشد و باید آن را در فایلی به نام Student.java قرار دهید.
/**
*
* @author it3du.ir
*/
public class Student {
private String name;
private String familyName;
private double grade;
public Student() {
this.name = "Name";
this.familyName = "FamilyName";
this.grade = 10.0d;
}
public Student(String name, String familyName, double grade) {
this.name = name;
this.familyName = familyName;
this.grade = grade;
}
public String getName() {
return name;
}
public String getFamilyName() {
return familyName;
}
public double getGrade() {
return grade;
}
}
بعد از تعریف کلاس Student باید آرایه ایی از اشیای (object) کلاس Student ایجاد کنیم. کد های زیر باید در فایلی به نام Main.java قرار بگیرد. سپس برنامه را اجرا کنید.
/**
*
* @author it3du.ir
*/
public class Main {
public Main() {
Student[] students = new Student[3];
students[0] = new Student("Ali", "Naseri", 15.64);
students[1] = new Student("Komeil", "Sharifi", 17.16);
students[2] = new Student("Nima", "Ghasemi", 12.42);
for (int i = 0; i < students.length; i++) {
System.out.println(students[i].getName() + " " + students[i].getFamilyName() + " " + students[i].getGrade());
}
}
public static void main(String[] args) {
new Main();
}
}
بعد از اجرای برنامه خروجی به صورت زیر خواهد بود
Ali Naseri 15.64
Komeil Sharifi 17.16
Nima Ghasemi 12.42
کد بالا بسیار واضح است. تنها نکته این است که برای دسترسی به متد ها و یا فیلد هایی از کلاس که می توانیم به آن ها دسترسی داشته باشیم از طریق شی موجود در آرایه ، باید اندیس آرایه را مشخص کنیم. برای مثال برای استفاده از شی موجود در خانه صفر آرایه به صورت زیر عمل می کنیم
System.out.println(students[0].getName());
می توانیم از یک شی Student در حلقه for کمک بگیریم. دستورات زیر را ببینید
for (int i = 0; i < students.length; i++) {
Student st = students[i];
System.out.println(st.getName() + " " + st.getFamilyName() + " " + st.getGrade());
}
یا می توانید از حلقه for-loop استفاده کنید به صورت زیر
for (Student student : students) {
System.out.println(student.getName() + " " + student.getFamilyName() + " " + student.getGrade());
}
در واقع در این حلقه کامپایلر به صورت خودکار از اندیس شماره 0 آرایه students شروع می کند و آن را در شی ای از Student قرار می دهد که این شی با نام student داخل حلقه قابل دسترس می باشد. در این حالت در هر گام حلقه به صورت خودکار به گام ها بعدی خواهد رفت.
آرایه های دو بعدی در جاوا
در بسیاری از موارد به آرایه های دو بعدی نیاز داریم. به عنوان مثال در ریاضی از ماتریس استفاده می کنیم و بسیاری از بازی از صفحات دو بعدی استفاده می کنند که نیاز به ماتریس داریم.
آرایه دو بعدی نیز مجموعه ایی از عناصر هم نوع هستند. می توان آرایه ایی با بعد های بیشتر از دو داشت ولی اغلب برنامه نویسان از آرایه های دوبعدی استفاده می کنند. جدول ضرب 10 در 10 می تواند مثال خوبی برای آرایه های دو بعدی باشد.
اعلان آرایه دو بعدی به صورت زیر می باشد
dataType[][] arrayName;
همانند آرایه های یک بعدی ، آرایه های دو بعدی نیز باید تخصیص حافظه پیدا کند (با عملگر new)
arrayName = new dataType[ROWS][COLS];
زمانی که یک آرایه دو بعدی را اعلان می کنیم ، باید مقدار سطر (ROWS) و ستون (COLS) آن را مشخص کنیم.
دستورات زیر را ببینید
int[][] numbers = new int[2][2];
دستور بالا آرایه ایی دو بعدی با تعداد سطر 2 و تعداد ستون 2 ایجاد می کند.
دستیابی به عناصر آرایه دو بعدی: با مثال زیر نحوه دستیابی به عناصر آرایه دو بعدی را شرح می دهیم. برای چاپ مقادیر آرایه دو بعدی به دو حلقه for نیاز داریم
int[][] n = {{1, 2}, {3, 4}};
for (int i = 0; i < n.length; i++) {
for (int j = 0; j < n[i].length; j++) {
System.out.print("n["+ i + "][" + j + "] : " + n[i][j] + " t");
}
System.out.println();
}
دستورات بالا چند نکته دارد. ایندکس اول شماره سطر های آرایه و ایندکس دوم تعداد ستون آرایه است. دستورات بالا از سطر اول شروع می کند و در حلقه for دوم همانند یک آرایه یک بعدی عناصر آن را چاپ می کند.
به یاد داشته باشید که دستور زیر
n.length
تعداد سطر های آرایه را بر میگرداند و در حلقه دوم دستور زیر
n[i].length
طول خانه های آرایه در سطر n ام آرایه را برمی گرداند.
خروجی دستورات زیر به صورت زیر خواهد بود ( بعد از اتمام حلقه دوم for یک دستور System.out.println وجود دارد که سطر جاری را رد می کند و باعث می شود عناصر هر سطر از آرایه در یک خط نمایش داده شوند)
n[0][0] : 1 n[0][1] : 2
n[1][0] : 3 n[1][1] : 4
همانند آرایه های یک بعدی ، آرایه های دو بعدی را نیز می توان به عنوان پارامتر به متد ها ارسال کرد
کلاس Vector در جاوا
یکی از محدودیت های آرایه ها ، اندازه ثابت آنها است. یعنی پس از اعلان شدن اندازه آن ها تغییر نمی کند. دستور زیر را ببینید
int[] n = {1,2,3};
آرایه ایی به اندازه 3 ایجاد کردیم. حالا اگر بخواهیم عنصر چهارمی به آرایه اضافه کنیم باید آرایه را در آرایه جدیدی کپی کنیم که اندازه آن 4 باشد. کلاس های Vector و Arrays متد هایی دارند که انجام این کار ها را برای ما آسان تر می کنند.
جاوا علاوه بر بر آرایه ، کلاس Vector را هم برای پیاده سازی لیست ها فراهم کرده است. برخلاف آرایه اندازه شی Vector در طول برنامه می تواند کم یا زیاد شود. بنابر این نگرانی راجع به اندازه آرایه نداریم.
هر عنصر شی بردار ، یک متغیر مرجع از نوع Object است. در جاوا ، Object یک کلاس از پیش تعریف شده است و متغیر مرجع از نوع Object می تواند آدرس هر شی را ذخیره کند
چون هر عنصر Vector یک متغیر مرجع است ، برای اضافه کردن عنصری به شی Vector ابتدا باید شی مناسبی ایجاد و داده ای را در آن ذخیره کنیم.
در ادامه بعد از توضیح کلاس Arrays دو مثال از چگونگی کار با این کلاس ها ارائه می دهیم. دستورات زیر یک نمونه از کلاس Vector با نوع متغیر مرجع String ایجاد می کند و اسامی فصل ها را در آن قرار می دهد
Vector str = new Vector();
str.addElement("Spring");
str.addElement("Summer");
str.addElement("Fall");
str.addElement("Winter");
for (int i = 0; i < str.size(); i++) {
System.out.println(str.get(i));
}
خروجی دستورات بالا به صورت زیر خواهد بود
Spring
Summer
Fall
Winter
همچنین می توانیم از کلاس Vector برای ایجاد برداری از انواع داده اولیه نیز استفاده کنیم. دستورات زیر را ببینید
int x;
Integer i;
دستور اول متغیر x از نوع int و دستور دوم متغیر i از نوع متغیر مرجع Integer را اعلان می کند.
علاوه بر این جاوا از autoboxing و auto-unboxing برای انواع داده اولیه استفاده می کند.
i = 25;
i = new Integer(25);
پس از اجرای هر یک از این دو دستور i به شی Integer اشاره می کند که مقدارش 25 است. دستور دوم autoboxing از نوع int دارد.
دستور زیر را ببینید
x = i;
این دستور که auto-unboxing نام دارد ، معادل دستور زیر است
X = i.intValue();
حالا دستورات زیر برداری از وع متغیر مرجع Double ایجاد می کند
Vector doubleList = new Vector();
doubleList.addElement(12.25);
doubleList.addElement(16.49);
دستورات بالا معادل دستورات زیر هستند
Vector doubleList = new Vector();
doubleList.addElement(new Double(12.25));
doubleList.addElement(new Double(16.49));
مثالی از کلاس Vector
سورس کد زیر را می توانید در فایلی به نام VectorExample.java ذخیره کنید و خروجی را مشاهده کنید. برنامه برخی از عملکرد های کلاس Arrays و Vector را نمایش می دهد.
import java.util.Arrays;
import java.util.Random;
import java.util.Vector;
/**
*
* @author http://www.it3du.ir
*/
public class VectorExample {
Vector vector = new Vector<>();
public static void setRandomValueInVector(Vector v) {
if (v == null) {
v = new Vector();
}
Random r = new Random();
for (int i = 0; i < 10; i++) {
v.addElement(r.nextInt(20)); // generate integer number 0-20
}
}
public static void printVectorValues(Vector v) {
if (v != null) {
if (v.size() > 0) {
for (int i = 0; i < v.size(); i++) {
System.out.println("vector[" + i + "]: " + v.get(i));
}
} else {
System.err.println("Your vector is empty!");
}
} else {
System.err.println("Your vector is null!");
}
}
public static void main(String[] args) {
VectorExample main = new VectorExample();
VectorExample.setRandomValueInVector(main.vector);
VectorExample.printVectorValues(main.vector);
}
}
می توانید انتشار قسمت ها جدید آموزش برنامه نویسی و به روز رسانی های جدید سایت را از کانال تلگرام ما دنبال کنید و یا از قسمت انتهایی سایت ، آدرس it3du را در سایر شبکه های اجتماعی پیدا کنید