JAVA ΕΝΟΤΗΤΑ 12 – ARRAYS

 


ΕΙΣΑΓΩΓΗ

Στο σημερινό δωρεάν μάθημα Java θα δούμε τι είναι και πως ορίζονται τα arrays. Επίσης θα δούμε πολλά απλά παραδείγματα για καλύτερη κατανόηση της θεωρίας.

DECLARING ARRAYS

Για να μπορέσουμε να κατανοήσουμε καλύτερα το πώς προγραμματιστικά μας διευκολύνει ένας array στην λογική της εφαρμογή μας όταν προστεθεί στο κώδικα μας, ας αναλύσουμε ένα απλό καθημερινό παράδειγμα.

Σκεφτείτε λοιπόν ότι μας έχουν αναθέσει την ανάπτυξη ενός java προγράμματος που σκοπός του είναι η καταγραφή και καταχώρηση μαθητών. Γενικότερα, υπάρχουν αρκετοί τρόποι να προσεγγίσετε αυτό το πρόβλημα και να το λύσετε, αλλά με βάση τη θεωρία που γνωρίζετε μέχρι τώρα η απάντηση δεν είναι και τόσο εύκολη.  Αν θεωρήσετε ότι κάθε τάξη δεν μπορεί να έχει περισσότερους από 20 μαθητές, ίσως να αποφασίσετε να δημιουργήσετε 20 διαφορετικές μεταβλητές με την κάθε μεταβλητή να αντιστοιχεί και σε έναν μαθητή. Αν η τάξη είχε 50 μαθητές τότε θα σκεφτόσασταν να δημιουργήσετε 50 διαφορετικές μεταβλητές. Ίσως να νομίζετε ότι μπορείτε να διαχειριστείτε αυτό τον αριθμό μεταβλητών αλλά πως θα διαχειριστείτε το πελατολόγιο μιας τράπεζας? Θα γράψετε 5000 ή 50000 μεταβλητές? Νομίζω ότι βλέπετε τώρα την σοβαρότητα του προβλήματος που έχετε να αντιμετωπίσετε. Επίσης, ας μην ξεχνάμε, εκτός από την διαχείριση των μεταβλητών είναι και η διαχείριση της μνήμης του συστήματος στο οποίο θα εκτελεστεί το πρόγραμμα σας.

Σαν array ορίζουμε μια συλλογή δεδομένων του ίδιου τύπου τα οποία μπορούμε να αντιπροσωπεύσουμε με ένα μόνο όνομα. Κάθε στοιχείο που ανήκει στον array, έχει συγκεκριμένο data type (ίδιο με εκείνο του array) ενώ η θέση του μέσα στον array ορίζεται από έναν index αριθμό. Η αρίθμηση του index ξεκινάει από το 0.

Για να ορίσουμε έναν array πρέπει να ακολουθήσουμε δύο βήματα:

1.      Να δώσουμε ένα όνομα στον array

2.      Να δημιουργήσουμε τον array χρησιμοποιώντας τη λέξη κλειδί new και ορίζοντας το μέγεθός του.

 

Στη Java, τα δεδομένα θα ανήκουν είτε στα primitive types ή θα είναι είδος object (αντικείμενα). Οι arrays είναι αντικείμενα και για αυτό άλλωστε δεν δημιουργούμε μια μεταβλητή αλλά ένα reference για να μπορέσουμε να τους διαχειριστούμε. Μην ανησυχείτε αν δεν καταλαβαίνετε την έννοια του reference και των αντικειμένων γενικότερα. Θα μιλήσουμε για αυτά πολύ σύντομα σε κάποια μελλοντική ενότητα. Για τώρα απλά δεχτείτε το συντακτικό δημιουργίας ενός array όπως έχει.

Πως λοιπόν ορίζουμε έναν array? Πρώτα δηλώνουμε το είδος των δεδομένων που θα δέχεται ο array όπως int, float, String κτλ, αμέσως μετά γράφουμε τα square brackets ( [ ] ) που στην ουσία ειδοποιεί την java ότι θα ορίσουμε έναν array και τέλος το όνομα του array. Μην ξεχάσετε να ολοκληρώσετε το statement κλείνοντας την εντολή με semicolon ( ; ) στο τέλος.

int [ ]students;

Η Java μας επιτρέπει να δηλώνουμε τα square brackets ( [ ] ) και μετά τον ορισμό του ονόματος του array. Αυτός είναι ένας δεύτερος εναλλακτικός τρόπος ορισμός ενός array που εξ ίσου χρησιμοποιείται.

int students[];

Μέχρι τώρα έχουμε απλά ορίσει το reference του array με το όνομα students. Δηλαδή έχουμε ορίσει ένα όνομα αλλά ακόμα δεν είναι συνδεδεμένο με κάποιο array. Αυτό είναι το επόμενο βήμα μας – να δημιουργήσουμε έναν καινούργιο array και να ορίσουμε το μέγεθός του. Για να δημιουργήσουμε έναν καινούργιο array χρησιμοποιούμε τη λέξη κλειδί new και αμέσως μετά ορίζουμε τον αριθμό που αντιπροσωπεύει το μέγεθος του array. Για να ορίσουμε λοιπόν έναν καινούργιο array ο οποίος δέχεται 20 μαθητές γράφουμε το εξής statement:

students = new int[20];

Συνήθως δεν ορίζουμε τον array σε δύο βήματα αλλά σε ένα. Ο λόγος που χρησιμοποιήσαμε δύο βήματα είναι για να καταλάβετε καλύτερα την θεωρία. Οπότε ο κώδικας:

int students[];

students = new int[20];

μπορεί να αντικατασταθεί με την εξής γραμμή:

int students[ ] = new int[20];

ACCESSING ARRAY ELEMENTS

Η παραπάνω εντολή δημιουργεί έναν array που δέχεται 20 ακέραιους αριθμούς. Αυτό που απομένει τώρα να μάθουμε είναι πως μπορούμε να τοποθετήσουμε τους αριθμούς των εξετάσεων των μαθητών σε κάθε μια από τις 20 θέσεις του array. Για αυτό το σκοπό χρησιμοποιείται ένας αριθμός που ονομάζεται index. Κάθε array αριθμεί τις θέσεις, για τις οποίες έχει δεσμεύσει χώρο στη μνήμη, με έναν ακέραιο αριθμό ξεκινώντας από το μηδέν. Οπότε για έναν array που δέχεται 20 ακέραιους αριθμούς, η αρίθμηση του index θα είναι από 0 έως 19.

 Αν θέλουμε λοιπόν να τοποθετήσουμε την βαθμολογία του πρώτου μαθητή στον array, θα πρέπει να γράψουμε τον εξής κώδικα:

students[0]=78;

Ενώ για τον δεύτερο μαθητή θα μπορούσαμε να βάλουμε τη βαθμολογία στην αμέσως διαθέσιμη θέσει που είναι:

students[1]=99;

Μέσα στη μνήμη του υπολογιστή έχουμε δημιουργήσει αυτό:


Μια ερώτηση που συχνά όλοι αναρωτούνται  όταν βλέπουν ένα τέτοιο παράδειγμα είναι τι τιμές θα υπάρχουν στις υπόλοιπες θέσεις του array που ακόμα δεν έχουμε εισάγει ακέραιους αριθμούς. Ένας array δεν είναι primitive type (όπως π.χ. int, float, char)  αλλά είναι αντικείμενο. Για αυτό άλλωστε καλούμε τη λέξη new κατά τη δημιουργία του. Ακόμα δεν έχουμε μιλήσει για αντικείμενα και ούτε χρειάζεται να μπούμε σε πολλές λεπτομέρειες αυτή τη στιγμή. Όμως, λόγω αυτής του της ιδιότητας, κάθε array αρχικοποιεί τις κενές θέσεις με το 0 αν είναι ένας array που δέχεται ακέραιους αριθμούς, με το 0.0 αν δέχεται double τιμές κτλ.

Αν τώρα επιθυμούσατε να γεμίσετε έναν array με κάποιες τυχαίες τιμές, θα μπορούσατε να χρησιμοποιήσετε ένα for loop και να ολοκληρώσετε αυτή τη πράξη πολύ γρήγορα. Χρησιμοποιώντας και πάλι ένα for loop θα μπορούσατε πολύ εύκολα να διαβάσετε τις τιμές που περιέχει.

App.java

package com.example;

public class App {

    public static void main(String[] args) {
        int students[] = new int[5];
        System.out.println("# Array without input values #");

        for (int i = 0; i < 5; i++) {
         System.out.println("index " + i + " has " + students[i]);
        }

        students[2] = 78;
        students[4] = 99;

        System.out.println("# Array with input values #");

        for (int i = 0; i < 5; i++) {
         System.out.println("index " + i + " has " + students[i]);
        }
    }
}

Output

# Array without input values #

index 0 has 0

index 1 has 0

index 2 has 0

index 3 has 0

index 4 has 0

# Array with input values #

index 0 has 0

index 1 has 0

index 2 has 78

index 3 has 0

index 4 has 99

Το παράδειγμα μας είναι πολύ απλό. Ορίζουμε εξ αρχής έναν array που μπορεί να δεχτεί μέχρι 5 ακέραιους αριθμούς. Αμέσως μετά ζητάμε, μέσα από ένα for loop, να δούμε τις default τιμές που υπάρχουν μέσα στον array. Το output μέχρι αυτό το σημείο μας δείχνει ότι όλες οι θέσεις του array περιέχουν τον αριθμό 0.

Στο επόμενο βήμα τοποθετούμε μερικές τιμές μέσα στον array χωρίς κάποια συγκεκριμένη σειρά και ερχόμαστε με ένα ακόμα for loop να τυπώσουμε στο terminal τις τιμές που περιέχει ο array αυτή τη φορά.

Προσέξτε λίγο τα όρια που ορίζουμε μέσα στη συνθήκη του for loop. Έχουμε ορίσει τη τοπική μεταβλητή i να είναι μικρότερη του 5 γιατί το index ξεκινάει τη μέτρηση από το 0 και στο συγκεκριμένο παράδειγμα φτάνει μέχρι το 4.

Αν προσπαθήσετε να ζητήσετε κάποια τιμή από ένα index αριθμό ο οποίος είναι εκτός των ορίων του array, τότε θα λάβετε ArrayUndexOutOfBounds runtime error από τη Java.

App.java

package com.example;

public class App {

    public static void main(String[] args) {
        int students[] = new int[5];

        students[2] = 78;
        students[4] = 99;
        students[5] = 63;
    }
}

Output

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5 at com.example.App.main(App.java:10)

ARRAY SIZE

Για να αποφύγουμε τυχόν λάθη όπως αυτό που δείξαμε στο προηγούμενο παράδειγμα, αντί να θέτουμε εμείς τους αριθμούς του index μέσα στη συνθήκη του array, χρησιμοποιούμε το attribute length που μας παρέχει το ίδιο το array. Αντί λοιπόν να γράφουμε i < 5, γράφουμε students.length αποφεύγοντας τυχόν ArrayIndexOutOfBounds λάθη. Ας δούμε πως θα μπορούσε να γραφτεί το προηγούμενο πρόγραμμα χρησιμοποιώντας τον ασφαλή τρόπο του attribute length.

App.java

package com.example;

public class App {

    public static void main(String[] args) {
        int students[] = new int[5];
        System.out.println("# Array without input values #");

        for (int i = 0; i < students.length; i++) {
          System.out.println("index " + i + " is " + students[i]);
        }

        students[2] = 78;
        students[4] = 99;

        System.out.println("# Array with input values #");

        for (int i = 0; i < students.length; i++) {
          System.out.println("index " + i + " is " + students[i]);
        }
    }
}

Output

# Array without input values #

index 0 is 0

index 1 is 0

index 2 is 0

index 3 is 0

index 4 is 0

# Array with input values #

index 0 is 0

index 1 is 0

index 2 is 78

index 3 is 0

index 4 is 99

ARRAY INITIALIZERS

Η Java μας επιτρέπει, εφόσον έχουμε ένα μικρό αριθμό δεδομένων, να ορίσουμε τον array και να περάσουμε σε αυτόν τα δεδομένα σε μόνο μια γραμμή κώδικα και χωρίς τη χρήση της λέξης new. Ο τρόπος που ορίζουμε ένα τέτοιο array είναι ο εξής:

int []students = {67, 49, 72, 83, 99};

 Ορίζουμε έναν array δηλώνοντας το όνομα του και το είδος των δεδομένων που δέχεται. Μέσα στα άγκιστρα δηλώνουμε τις τιμές που θα περάσουμε στον array. Ο τρόπος είναι απλός αλλά ο κανόνας της Java απαιτεί η δήλωση του ονόματος του array όπως και η ανάθεση τιμών σε αυτόν να γίνει στην ίδια γραμμή κώδικα.


 

App.java

package com.example;

public class App {

    public static void main(String[] args) {
        int[] odds = { 1, 3, 5, 7, 9 };
        System.out.println("odds.length = " + odds.length);

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

        String[] daysOfWeek = { "Saturday", "Sunday", "Monday", "Tuesday","Wednesday", "Thursday", "Friday" };
        System.out.println("daysOfWeek.length = " + daysOfWeek.length);

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


Output

odds.length = 5

odds[0] = 1

odds[1] = 3

odds[2] = 5

odds[3] = 7

odds[4] = 9

daysOfWeek.length = 7

daysOfWeek[0] = Saturday

daysOfWeek[1] = Sunday

daysOfWeek[2] = Monday

daysOfWeek[3] = Tuesday

daysOfWeek[4] = Wednesday

daysOfWeek[5] = Thursday

daysOfWeek[6] = Friday

FOREACH LOOPS

Εκτός από το for loop έχουμε έναν ακόμα γρήγορο τρόπο για να διαβάζουμε τιμές από έναν array που ονομάζεται foreach loop. Δηλώνουμε μια τοπική μεταβλητή στο foreach loop με ότι όνομα επιθυμούμε και το κατάλληλο data type. Μετά χρησιμοποιούμε το colon ( : ) και αμέσως μετά ακολουθεί το όνομα του array. Η μεταβλητή αυτόματα θα λαμβάνει μια προς μια τις τιμές που περιέχει ο array.

App.java

package com.example;

public class App {

    public static void main(String[] args) {
        String[] daysOfWeek = { "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" };

        for (String days : daysOfWeek) {
            System.out.println(days);
        }
    }
}

Output

Saturday

Sunday

Monday

Tuesday

Wednesday

Thursday

Friday

MULTIDIMENSIONAL ARRAYS

Όλα τα παραδείγματα που έχουμε αναλύσει μέχρι τώρα περιέχουν arrays μονής διάστασης. Πως θα μπορούσαμε να ορίσουμε ένα array με δύο ή περισσότερες διαστάσεις? Ο τρόπος είναι απλός για ακόμη μια φορά – προσθέτουμε τόσα square brackets ( [ ] ) όσες είναι οι διαστάσεις που θέλουμε να έχει ο array.

int [ ][ ] courses = new int[3][2];

Στη πραγματικότητα έχουμε δημιουργήσει αυτό:



Ας δούμε ένα απλό παράδειγμα ενός array που περιέχει δύο διαστάσεις.

App.java

package com.example;

public class App {

    public static void main(String[] args) {
        int[][] courses = new int[3][2];
        courses[1][1] = 10;
        courses[2][0] = 20;

        for (int row = 0; row < courses.length; row++) {
            for (int col = 0; col < courses[row].length; col++) {
                System.out.println(courses[row][col]);
            }
            System.out.println();
        }
    }
}

Output

0

0

 

0

10

 

20

0




Οι array είναι πολύ χρήσιμοι για εμάς τους προγραμματιστές όμως ο συγκεκριμένος τύπος array παρουσιάζει αρκετές αδυναμίες με κυριότερη αυτή που έχει να κάνει με τη μη δυνατή αλλαγή του μεγέθους του αφότου οριστεί. Αυτό είναι ένα μεγάλο μειονέκτημα. Σκεφτείτε πάλι το παράδειγμα με τους πελάτες μιας τράπεζας. Πόσο μεγάλο μπορείτε να ορίσετε εξ αρχής τον array σας? 10000 ή 50000? Και αν μέσα σε μικρό χρονικό διάστημα οι πελάτες της τράπεζας διπλασιαστούν πως θα το αντιμετωπίσετε αυτό το πρόβλημα? Και αν πάλι οι πελάτες δεν διπλασιαστούν, μόνο και μόνο που έχετε ορίσει ένα τόσο μεγάλου μεγέθους array, έχετε δεσμεύσει ένα πολύ μεγάλο κομμάτι της μνήμης του συστήματος σας χωρίς καν να το χρειάζεστε.

Εκτός από το πρόβλημα της μνήμης υπάρχουν και άλλα προβλήματα που έχουμε να αντιμετωπίσουμε με αυτό το είδος array όπως ταυτόχρονη πρόσβαση στα δεδομένα από διαφορετικά αντικείμενα και προβλήματα απόδοσης και ταχύτητας στην αναζήτηση δεδομένων.

Όταν κάποια στιγμή θα καλύψουμε την θεωρία για τα αντικείμενα, θα μπορέσουμε να μιλήσουμε για την ευρύτερη κατηγορία στην οποία ανήκουν τα arrays που ονομάζεται collections και περιέχει άλλου είδους arrays πιο ευέλικτους και με περισσότερες δυνατότητες.

Μην ξεχάσετε να κάνετε ένα μικρό donation έτσι ώστε αυτό το blog να μεγαλώσει ακόμα πιο πολύ και να έχει περισσότερες δυνατότητες στην online παράδοση δωρεάν μαθημάτων.


full-width

Post a Comment

0 Comments