BETA

Μαθαίνοντας την Java-ARRAYS [μάθημα 10]

Εικόνα Michail

Συνεχίζουμε τα μαθήματα εκμάθησης της Java, έχοντας ήδη κάνει το πρώτο εισαγωγικό μάθημα και έχοντας δει,πως μπορουμε να εγκαταστήσουμε το NetBeans, προκειμένου να δημιουργήσουμε τις εφαρμογές μας και στη συνεχεια δημιουργώντας την πρωτη μας εφαρμογή.
Έχοντας δει κιόλας, σχετικά με τα LANGUAGE FUNDAMENTALS και στη συνέχεια, Ονομασία Μεταβλητών, και τα INTEGER TYPES, καθώς και τα Floating Point Types, μα και καθορισμό των Boolean και Char Data types, συνεχίζουμε με το 10ο μάθημα της σειράς.
[box color=blue]Σε αυτή την φάση για τα εκπαιδευτικά μαθήματα χρησιμοποιούμε το λειτουργικό σύστημα Windows, μα οι διαφορές είναι ελάχιστες, ως μηδαμινές και στα υπόλοιπα λειτουργικά[/box]
Στο σημερινό μάθημα θα αναφερθούμε στους πίνακες ή όπως είναι γνωστοί στην αγγλική προγραμματιστική ορολογία – arrays.
Ενώ θα χρησιμοποιήσουμε το on-line documentation της java σαν τον κύριο οδηγό μας για την δομή ανάπτυξης του μαθήματος, αλλά θα δώσουμε και επιπλέον χρήσιμες συμβουλές για την καλύτερη ανάπτυξη των προγραμμάτων μας.

Το πρώτο πράγμα που πρέπει να αναφερθεί στην ανάλυση μας είναι ότι ένας array δεν ανήκει στα primitive types (δηλαδή double, integer, κτλ) αλλά ανήκει στην κατηγορία του αντικειμενοστραφή προγραμματισμού μιας και πρόκειται για αντικείμενο.
Αν και δεν έχουμε μιλήσει ακόμα για κλάσεις και αντικειμενοστραφή προγραμματισμό (δηλαδή Object Oriented Programming), αυτό δεν θα μας εμποδίσει καθόλου να καταλάβουμε τον ορισμό ενός array όσο και να το χρησιμοποιήσουμε αποδοτικά στο πρόγραμμα μας.

Ένας array λοιπόν είναι ένα αντικείμενο που έχει την ικανότητα και την ιδιότητα να μπορεί να δέχεται και να αποθηκεύει έναν προκαθορισμένο αριθμό στοιχείων με την προϋπόθεση ότι όλα ανήκουν στο ίδιο είδος δεδομένων.
Δηλαδή τα στοιχεία που θα αποθηκευτούν θα είναι όλα ακέραιοι αριθμοί, ή όλα δεκαδικοί, ή όλοι χαρακτήρες κτλ.
Το μέγεθος του array καθορίζεται την ίδια χρονική στιγμή της δημιουργίας του.
Εδώ όμως πρέπει να συμβιβαστούμε με τον περιορισμό που συνοδεύει την δημιουργία ενός array – δεν επιτρέπεται καμία αλλαγή στο μέγεθος του array μετά τον αρχικό ορισμό του.
Με άλλα λόγια ένας array δεν έχει την ικανότητα να αυξομειώνεται δυναμικά ανάλογα με τον αριθμό των στοιχείων κατά την διάρκεια εκτέλεσης ενός προγράμματος.
Η πιο κάτω εικόνα μας δείχνει πιο παραστατικά την δομή ενός array την οποία θα αναλύσουμε αμέσως τώρα:

Κάθε στοιχείο πληροφορίας που αποθηκεύεται στον array ονομάζεται element, και σε κάθε element αντιστοιχεί ένας αριθμός (index) ο οποίος αντιπροσωπεύει την θέση του στοιχείου στον array. Η αρίθμηση του index αρχίζει από τον αριθμό μηδέν (0), δηλαδή πάντα έναν αριθμό λιγότερο από τον συνολικό αριθμό των στοιχείων του array.
Ας μιλήσουμε όμως για το παράδειγμα που απεικονίζεται στην πιο πάνω εικόνα πιο αναλυτικότερα.

Ορίζουμε έναν πίνακα (array) με συνολικό αριθμό στοιχείων (elements) 10.
Το όνομα ενός πίνακα πάντα συνοδεύεται από τα σύμβολα [ και ] για να ξεχωρίζει από τον ορισμό οποιασδήποτε άλλης μεταβλητής.
Για να αναφερθούμε σε κάθε ένα από τα στοιχεία που είναι αποθηκευμένα στον array πρέπει να χρησιμοποιήσουμε τον ανάλογο αριθμό (index) που αντιπροσωπεύει την τοποθεσία τους.
Για να καλέσουμε π.χ. το ένατο στοιχείο του array πρέπει χρησιμοποιήσουμε το index 8 αφού η αρίθμηση για τα indexes είναι πάντα ένα αριθμό μικρότερη από τον συνολικό αριθμό των στοιχείων του πίνακα.
Το πιο κάτω πρόγραμμα που προέρχεται από την ιστοσελίδα της sun, μας παρουσιάζει την πιο απλή σύνταξη και χρησιμοποίηση ενός πίνακα τον οποίο αφότου τον ορίσουμε και τοποθετήσουμε δεδομένα σε όλες τις διαθέσιμες θέσεις που παρέχει, διαβάζουμε τις τιμές και τις παρουσιάζουμε στην οθόνη του χρήστη.


Line 7 – Line 10: Εδώ ορίζουμε έναν καινούργιο πίνακα (array) με το όνομα anArray και του δίνουμε μέγεθος χωρητικότητας στοιχείων 10 που πρέπει να είναι όλα ακέραιοι αριθμοί (integers)
Για άλλη μια φορά επαναλαμβάνουμε ότι για ξεχωρίζει ο ορισμός ενός array από τον ορισμό οποιασδήποτε άλλης μεταβλητής συνοδεύεται από τα σύμβολα [ και ]. Τα συγκεκριμένα σύμβολα μπορούν να τοποθετηθούν ή πριν ή μετά το όνομα του array.
Η Oracle όμως όπως και οι δημιουργοί της Java υποστηρίζουν ότι θα πρέπει να τοποθετούνται αμέσως μετά το data type και μπροστά από το όνομα του array όπως και στο παράδειγμά μας (int[ ] anArray;).
Όμως για κανέναν από τους δύο τρόπους εγγραφής δεν θα παραπονεθεί ο compiler της java.

Επίσης, θα μπορούσαμε να είχαμε ορίσει τον πίνακα και το μέγεθός του σε μία γραμμή κώδικα που επιδεικνύει έναν πιο ώριμο τρόπο γραψίματος java κώδικα :

int [ ]anArray = new int[10];

Οπότε το συμπέρασμά που βγάζουμε είναι ότι για τον ολοκληρωμένο ορισμό του array χρειάζεται να καθορίσουμε το όνομα του:

int [ ]anArray = new int[10];

το είδος των δεδομένων που θα δέχεται

int [ ]anArray = new int[10];

και το μέγεθός του

int [ ]anArray = new int[10] ;

Έχουμε αναφέρει επανειλημμένα ότι ένας πίνακας μπορεί να οριστεί να δέχεται και άλλα είδη δεδομένων.
Ο επόμενος πίνακας, ο οποίος προέρχεται από την ιστοσελίδα της Sun  μας δίνει μια λίστα με όλα τα πιθανά data type δεδομένων που μπορεί να δεχτεί ένας array:

Line 13 – Line 24: Εδώ βλέπουμε τον τρόπο με τον οποίο αναθέτουμε ακέραιες τιμές για κάθε στοιχείο του πίνακα.
Το όνομα του πίνακα μαζί με το index προσδιορίζουν ένα μοναδικό στοιχείο στο οποίο αναθέτουν μια τιμή. Οπότε στο index [0] του anArray πίνακα αναθέτουμε την τιμή 100, στο index [1] την τιμή 200 κτλ.

Line 26 – Line 45: Για να μπορέσουμε να δούμε τις τρέχων τιμές που έχουν αποθηκευτεί για κάθε στοιχείο του πίνακα ακολουθούμε την ίδια διαδικασία όπως και στα βήματα της ανάθεσης τιμών.
Δηλαδή, μπορούμε να διαβάσουμε την τρέχων τιμή οποιουδήποτε στοιχείου στου πίνακα χρησιμοποιώντας το όνομα του πίνακα και τον αριθμό index που του αντιστοιχεί.

Εάν θέλαμε να μειώσουμε τον αριθμό των γραμμών κώδικα στο πρόγραμμα μας και να του δώσουμε μια πιο επαγγελματική προσέγγιση, τότε δεν θα διαβάζαμε τις τιμές των στοιχείων του πίνακα μεμονωμένα αφιερώνοντας για κάθε στοιχείο και μια γραμμή κώδικα, αλλά θα δημιουργούσαμε ένα βρόγχο (loop) το οποίο θα έκανε τόσες επαναλήψεις όσες είναι απαραίτητες για να διαβαστούν όλες οι τιμές. Αυτό είναι ένα θέμα που θα μας απασχολήσει σύντομα στα μαθήματα μας.

Επίσης στην Java έχουμε την ικανότητα να ορίσουμε το μέγεθος του array όχι μόνο αριθμητικά, όπως είδαμε στο προηγούμενο παράδειγμα, αλλά δηλώνοντας τις ίδιες τις τιμές που θα αποθηκευτούν.
Για παράδειγμα, η εντολή int[ ] anArray = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000}; ορίζει έναν πίνακα με 10 στοιχεία.
Η πιο πάνω σύνταξη ορίζει έναν πίνακα με το όνομα anArray, ορίζει το μέγεθος του, και ταυτόχρονα γεμίζει τον array με αριθμητικά δεδομένα τα οποία στο είδος τους συμφωνούν με το int είδος που έχουμε ορίσει .
Αυτός ο τρόπος δημιουργίας ενός πίνακα δεν απαιτεί την χρήση της λέξης new, ενώ τα δεδομένα πρέπει να περικλείονται ανάμεσα στα σύμβολα { και } και να χωρίζονται μεταξύ τους με κόμμα.
Τα δεδομένα αποθηκεύονται ακριβώς με την σειρά με την οποία δηλώνονται.
Στο παράδειγμά μας, στην index τοποθεσία 0 είναι τώρα αποθηκευμένος ο αριθμός 100, ενώ στο δέκατο στοιχείο (index 9) έχει αποθηκευτεί ο αριθμός 1000.
Αυτός ο τρόπος σύνταξης και δημιουργίας ενός array είναι βολικός και εύχρηστος όταν το μέγεθος των array είναι μικρό.

Επίσης δεν περιοριζόμαστε μόνο σε αριθμούς – κάλλιστα μπορεί ένας πίνακας να περιέχει χαρακτήρες ή ακόμα String ονομάτων:

String [ ] days={“Saturday”, “Sunday”, “Monday”, “Tuesday”};

Το είδος των πινάκων για το οποίο έχουμε συζητήσει μέχρι τώρα είναι μονοδιάστατοι. Δηλαδή πρακτικά αποτελούνται από μια στήλη δεδομένων.
Όμως στην Java δεν υπάρχει περιορισμός στις διαστάσεις που μπορεί να έχει ένας πίνακας.
Συνήθως χρησιμοποιούμε πίνακες δύο διαστάσεων που μπορούν να αντιπροσωπεύσουν την δημιουργία στηλών και γραμμών.
Ο τρόπος δημιουργίας τους είναι πραγματικά πολύ απλός – απλά προσθέτουμε ένα δεύτερο ζεύγος [ ] δίπλα στο πρώτο αν πρόκειται για πίνακα δύο διαστάσεων, ενώ θα χρειαστούμε τρία ζεύγη [ ] για να ορίσουμε έναν τρισδιάστατο πίνακα.
Η δυνατότητα ύπαρξης περισσοτέρων από μια διάστασης, μας δίνει επίσης το πλεονέκτημα να έχουμε διαφορετικά μεγέθη πίνακες όπως παρουσιάζει το πιο κάτω παράδειγμα:

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

Line 6 – Line 8: Ορίζουμε λοιπόν έναν πίνακα με το όνομα names ο οποίος έχει δύο διαστάσεις.
Σε κάθε διάσταση αναθέτουμε από ένα γκρουπ τιμών σε μορφή String (δηλαδή λέξεις που περιέχουν περισσότερα από ένα αλφαβητικό σύμβολο).
Το πρώτο γκρουπ δεδομένων αποτελείται από τρεις λέξεις οι οποίες θα αποθηκευτούν στην πρώτη διάσταση του πίνακα, ενώ το δεύτερο γκρουπ δεδομένων που αποτελείται από δύο λέξεις θα αποθηκευτούν στην δεύτερη διάσταση του πίνακα.

Line 11 – Line 13: Στις συγκεκριμένες γραμμές κώδικα, ζητάμε να δούμε τα στοιχεία που είναι αποθηκευμένα στον πίνακα με έναν καθορισμένο τρόπο. Το επιθυμητό αποτέλεσμα είναι να δούμε τις μικρές φράσεις Mr. Smith και Ms. Jones να εμφανίζονται στην οθόνη μας μετά το τέλος της εκτέλεσης τους προγράμματος.
Για να το επιτύχουμε αυτό θα πρέπει να καλέσουμε τις σωστές λέξεις από τις κατάλληλες τοποθεσίες του πίνακα ο οποίος έχει διάσταση 3 χ 2. Αν θέλαμε να παρουσιάσουμε με πιο γραφικό τρόπο την δομή του πίνακα θα είχαμε μια εικόνα όπως αυτή που ακολουθεί:

names[0][0]=”Mr.”;
names[0][1]=”Mrs.”;
names[0][2]=”Ms.”;
names[1][0]=”Smith”;
names[1][1]=”Jones”;

Ένα πρόβλημα που παρουσιάζεται συχνά με την χρήση ενός πίνακα είναι η ανάγκη αλλαγής του μεγέθους του.
Πολλές φορές δεν μπορούμε εξ αρχής να γνωρίζουμε το ακριβές μέγεθος του και στην προσπάθεια μας να μην σπαταλήσουμε άδικα την μνήμη του υπολογιστή μας τον ορίζουμε με ένα μικρό αριθμό στοιχείων.
Όταν όμως κατά την διάρκεια εκτέλεσης της εφαρμογής ανακαλύπτουμε ότι ο αριθμός των στοιχείων δεν αρκεί για να καλύψει όλα τα δεδομένα που θέλουμε να αποθηκεύσουμε, τότε απλά δεν μπορούμε να κάνουμε τίποτα για τον ίδιο τον πίνακα για να διορθώσουμε το μέγεθός του και πρέπει να βρούμε άλλο τρόπο προσωρινής αποθήκευσης των στοιχείων μας.
Αυτός ο άλλος τρόπος θα είναι απλά να δημιουργηθεί ένας μεγαλύτερος καινούργιος πίνακας με σκοπό να μεταφέρουμε τα δεδομένα μας εκεί από τον μικρότερο πίνακα.
Η αντιγραφή δεδομένων όμως από έναν πίνακα σε έναν άλλον δεν είναι εύκολη προσπάθεια και απαιτεί αρκετές γραμμές κώδικα για να λειτουργήσει σωστά.
Η λύση σε αυτό το πρόβλημα έρχεται από την ίδια την Sun με την μορφή μιας έτοιμης μεθόδου με το όνομα arraycopy.
Η συγκεκριμένη μέθοδος προϋποθέτει την χρησιμοποίηση πέντε μεταβλητών οι οποίες έχουν τον εξής σκοπό:

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

Object src : προσδιορίζει τον πίνακα από τον οποίο θα προέλθουν τα δεδομένα.

int srcPos: ορίζει την θέση του index στον αρχικό πίνακα από την οποία θα αρχίσουμε να διαβάζουμε τα δεδομένα.

Object dest: προσδιορίζει το όνομα του καινούργιου πίνακα στον οποίο θα μεταφερθούν τα δεδομένα.

int destPos : ορίζει την θέση του index στον τελικό πίνακα από την οποία θα αρχίσουμε να αποθηκεύονται τα δεδομένα.

int lenght: αντιπροσωπεύει τον αριθμό των στοιχείων που θέλουμε να αντιγραφούν.

Στο πιο παρακάτω παράδειγμα, το πρόγραμμα ArrayCopyDemo σαν πρώτο βήμα, αποθηκεύει την λέξη “decaffeinated” σε μεμονωμένους χαρακτήρες (ένα γράμμα σε κάθε στοιχείο) στον πίνακα copyFrom.
Στο δεύτερο βήμα, αντιγράφει αρκετά γράμματα στον δεύτερο πίνακα ώστε να σχηματιστεί η λέξη “caffein”.
Ας δούμε όμως πρώτα τον κώδικα του προγράμματος συνοδευόμενο από το αποτέλεσμα της εκτέλεσης του και μετά ας εξηγήσουμε τα κύρια μέρη του:

Line 6 – Line 8: Ο πρώτος πίνακας που δημιουργείται με το όνομα copyFrom θα έχει μέγεθος ίσο με τον αριθμό των χαρακτήρων που θα αποθηκευτούν. Ο δεύτερος πίνακας απλά ορίζεται με αρχικό μέγεθος 7.
Και οι δύο πίνακες έχουν οριστεί να δέχονται char data types.

Line 10 – Εδώ εκμεταλλευόμαστε την δυνατότητα της μεθόδου arraycopy όπου μας επιτρέπει να αντιγράψουμε δεδομένα από έναν πίνακα σε έναν άλλο.
Με βάση την μικρή ανάλυση που κάναμε, εξηγώντας την σημασία κάθε παραμέτρου που απαιτεί η μέθοδο για την σωστή λειτουργία της, μπορούμε να δώσουμε την παρακάτω εξήγηση:

Αντιγράφουμε ένα πίνακα με το όνομα copyFrom ξεκινώντας από το στοιχείο που βρίσκεται αποθηκευμένο στο index 2 (δηλαδή στην θέση 3) μέχρι το τέλος της σειράς των χαρακτήρων. Κάνουμε την επικόλληση των στοιχείων σε έναν καινούργιο πίνακα με το όνομα copyTo ξεκινώντας από το index 0 και μέχρι το index 7.
Αυτό σημαίνει ότι ορίζουμε ένα συγκεκριμένο όριο στον αριθμό των στοιχείων που θα δεχτεί ο καινούργιος πίνακας.
Πιο συγκεκριμένα, αν και τα στοιχεία που έχουμε αντιγράψει ήδη από τον πίνακα copyFrom αριθμούνται σε 11, μόνο τα 7 πρώτα από αυτά θα αποθηκευτούν στον καινούργιο πίνακα copyTo.

Line 11 – Σε αυτή την τελευταία γραμμή κώδικα, ζητάμε να δούμε τα στοιχεία που είναι αποθηκευμένα στον πίνακα copyTo.
Αυτός ο τρόπος είναι μια συντομογραφία, αν μου επιτρέπεται να χρησιμοποιήσω αυτή την έκφραση, για τον απλούστατο λόγο ότι δεν είναι απαραίτητο να ζητήσω με μεμονωμένες γραμμές κώδικα να εμφανιστεί κάθε στοιχείο ξεχωριστά όπως κάναμε στο προηγούμενο πρόγραμμα.
Με τον συγκεκριμένο τρόπο εγγραφής, ενώ κάθε χαρακτήρας, εσωτερικά στην μνήμη του υπολογιστή, διαβάζεται ξεχωριστά το τελικό αποτέλεσμα είναι να εμφανιστούν όλοι μαζί οι χαρακτήρες με την μορφή μιας ενιαίας λέξης γιατί ζητάμε να δούμε το αποτέλεσμα σε μορφή String.
Θυμηθείτε ότι ένα String αντιπροσωπεύει δύο ή και περισσότερους χαρακτήρες μαζί στην ίδια λέξη.
Όπως είχαμε αναφέρει η συνήθης πράξη δεν είναι να κάνουμε επικόλληση και μεταφορά στοιχείων από ένα πίνακα κάποιου μεγέθους σε έναν άλλον πίνακα μικρότερου μεγέθους, αλλά σε έναν τελικό πίνακα με μεγαλύτερο μέγεθος από τον αρχικό.
Ο τρόπος όμως σύνταξης της εντολής θα είναι ακριβώς ο ίδιος.

-Εδώ ολοκληρώσαμε το σημερινό μάθημα το οποίο ήταν μια αποκλειστική ανάλυση στους πίνακες και στις ιδιότητες τους.

Μιχάλης Κασάπογλου(http://kassapoglou.com)

  • Σχόλια

0 Comments:

Scroll to Top