Προγραμματισμός

Συμβουλή Java 112: Βελτίωση της συμβολής συμβολοσειρών πλούσιων σε πληροφορίες

Οι περισσότεροι προγραμματιστές Java έχουν χρησιμοποιήσει το java.util.StringTokenizer τάξη κάποια στιγμή ή άλλο. Είναι μια εύχρηστη τάξη που βασικά συμβολίζει (διακόπτει) τη συμβολοσειρά εισόδου με βάση ένα διαχωριστικό και παρέχει τα διακριτικά κατόπιν αιτήματος. (Tokenization είναι η πράξη της μετατροπής ακολουθιών χαρακτήρων σε διακριτικά που κατανοούνται από το πρόγραμμά σας.)

Αν και βολικό, StringTokenizerΗ λειτουργικότητα είναι περιορισμένη. Η τάξη απλά αναζητά τον οριοθέτη στη συμβολοσειρά εισόδου και σπάει τη συμβολοσειρά μόλις βρεθεί ο οριοθέτης. Δεν ελέγχει για συνθήκες όπως εάν ο οριοθέτης βρίσκεται μέσα σε ένα υπόστρωμα, ούτε επιστρέφει το διακριτικό ως "" (μήκος συμβολοσειράς 0) όταν βρεθούν δύο διαδοχικά οριοθέτες στην είσοδο. Για την εκπλήρωση αυτών των περιορισμών, η πλατφόρμα Java 2 (JDK 1.2 και μετά) συνοδεύεται από το BreakIterator τάξη, η οποία έχει βελτιωθεί το tokenizer StringTokenizer. Δεδομένου ότι μια τέτοια τάξη δεν υπάρχει στο JDK 1.1.x, οι προγραμματιστές συχνά αφιερώνουν πολύ χρόνο γράφοντας ένα πρωτότυπο tokenizer που πληροί τις απαιτήσεις τους. Σε ένα μεγάλο έργο που περιλαμβάνει χειρισμό μορφών δεδομένων, δεν είναι ασυνήθιστο να βρούμε πολλές τέτοιες προσαρμοσμένες τάξεις.

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

Περιορισμοί StringTokenizer

Μπορείτε να δημιουργήσετε ένα StringTokenizer χρησιμοποιώντας έναν από τους ακόλουθους τρεις κατασκευαστές:

  1. StringTokenizer (String sInput): Διαλείμματα σε λευκό διάστημα ("", "\ t", "\ n").
  2. StringTokenizer (String sInput, String sDelimiter): Διακόπηκε sDelimiter.
  3. StringTokenizer (String sInput, String sDelimiter, boolean bReturnTokens): Διακόπηκε sDelimiter, αλλα αν bΕπιστροφήTokens έχει οριστεί ως αληθές, τότε ο διαχωριστής επιστρέφεται επίσης ως διακριτικό.

Ο πρώτος κατασκευαστής δεν ελέγχει αν η συμβολοσειρά εισόδου περιέχει υποστρώματα. Όταν η χορδή "γεια. Σήμερα \" πηγαίνω στην πατρίδα μου " συμβολίζεται σε κενό διάστημα, το αποτέλεσμα είναι σε διακριτικά γεια., Σήμερα, "ΕΓΩ, είμαι, ", μετάβαση, αντί γεια., Σήμερα, "Εγω ειμαι ", μετάβαση.

Ο δεύτερος κατασκευαστής δεν ελέγχει τη διαδοχική εμφάνιση των οριοθετών. Όταν η χορδή "βιβλίο, συγγραφέας, έκδοση ,,, ημερομηνία δημοσίευσης" επισημαίνεται στις ",", ο StringTokenizer επιστρέφει τέσσερα διακριτικά με τιμές Βιβλίο, συντάκτης, δημοσίευση, και ημερομηνία δημοσίευσης αντί για τις έξι τιμές Βιβλίο, συντάκτης, δημοσίευση, "", "", και ημερομηνία δημοσίευσης, όπου "" σημαίνει συμβολοσειρά μήκους 0. Για να πάρετε έξι, πρέπει να ορίσετε το StringTokenizer'μικρό bΕπιστροφήTokens παράμετρος σε true.

Το χαρακτηριστικό της ρύθμισης της παραμέτρου σε true είναι σημαντικό καθώς δίνει μια ιδέα για την παρουσία διαδοχικών οριοθετών. Για παράδειγμα, εάν τα δεδομένα λαμβάνονται δυναμικά και χρησιμοποιούνται για την ενημέρωση ενός πίνακα σε μια βάση δεδομένων, όπου τα διακριτικά εισαγωγής αντιστοιχούν στις τιμές της στήλης, τότε δεν μπορούμε να χαρτογραφήσουμε τα διακριτικά με στήλες βάσης δεδομένων, καθώς δεν είμαστε σίγουροι ποιες στήλες πρέπει να οριστούν προς την "". Για παράδειγμα, θέλουμε να προσθέσουμε εγγραφές σε έναν πίνακα με έξι στήλες και τα δεδομένα εισαγωγής περιέχουν δύο διαδοχικά οριοθέτες. Το αποτέλεσμα από StringTokenizer σε αυτήν την περίπτωση είναι πέντε διακριτικά (καθώς δύο διαδοχικά οριοθέτες αντιπροσωπεύουν το διακριτικό "", οι οποίες StringTokenizer παραμέληση), και πρέπει να θέσουμε έξι πεδία. Επίσης, δεν γνωρίζουμε πού εμφανίζεται ο διαδοχικός οριοθέτης, σε ποια στήλη πρέπει να οριστεί "".

Ο τρίτος κατασκευαστής δεν θα λειτουργήσει εάν ένα ίδιο το διακριτικό είναι ίσο (σε μήκος και τιμή) με τον οριοθέτη και βρίσκεται σε ένα υπόστρωμα. Όταν η χορδή "βιβλίο, συγγραφέας, έκδοση, \", \ ", ημερομηνία δημοσίευσης" συμβολίζεται (αυτή η συμβολοσειρά περιέχει , ως διακριτικό, το οποίο είναι ίδιο με το διαχωριστικό του) στη συμβολοσειρά ,, το αποτέλεσμα είναι Βιβλίο, συντάκτης, δημοσίευση, ", ", ημερομηνία δημοσίευσης (με έξι μάρκες) αντί για Βιβλίο, συντάκτης, δημοσίευση, , (ο χαρακτήρας κόμμα), ημερομηνία δημοσίευσης (με πέντε μάρκες). Σας υπενθυμίζουμε, ακόμη και τη ρύθμιση bΕπιστροφήTokens (τρίτη παράμετρος έως StringTokenizerσε αληθινό δεν θα σας βοηθήσει σε αυτήν την περίπτωση.

Βασικές ανάγκες ενός tokenizer

Πριν ασχοληθείτε με τον κωδικό, θα πρέπει να γνωρίζετε τις βασικές ανάγκες ενός καλού tokenizer. Δεδομένου ότι οι προγραμματιστές Java είναι συνηθισμένοι στο StringTokenizer class, ένας καλός tokenizer θα πρέπει να έχει όλες τις χρήσιμες μεθόδους που παρέχει η τάξη, όπως hasMoreTokens (), nextToken (), countTokens ().

Ο κωδικός για αυτήν την συμβουλή είναι απλός και κυρίως αυτονόητος. Βασικά, έχω χρησιμοποιήσει το StringTokenizer τάξη (δημιουργήθηκε με bΕπιστροφήTokens οριστεί σε true) εσωτερικά και παρέχονται μέθοδοι που αναφέρονται παραπάνω. Δεδομένου ότι σε ορισμένες περιπτώσεις ο διαχωριστής απαιτείται ως διακριτικά (πολύ σπάνιες περιπτώσεις) ενώ σε ορισμένες δεν είναι, ο διακριτής πρέπει να παρέχει τον διαχωριστή ως διακριτικό κατόπιν αιτήματος. Όταν δημιουργείτε ένα Ισχυρό Tokenizer αντικείμενο, περνώντας μόνο τη συμβολοσειρά εισόδου και τον οριοθέτη, χρησιμοποιεί εσωτερικά ένα StringTokenizer με bΕπιστροφήTokens οριστεί σε αληθινό. (Ο λόγος για αυτό είναι εάν a StringTokenizer δημιουργείται χωρίς bΕπιστροφήTokens οριστεί σε true, τότε περιορίζεται στην αντιμετώπιση των προβλημάτων που αναφέρθηκαν προηγουμένως). Για τον σωστό χειρισμό του tokenizer, ο κώδικας ελέγχει εάν bΕπιστροφήTokens έχει οριστεί ως αληθής σε μερικά σημεία (υπολογισμός του συνολικού αριθμού των διακριτικών και nextToken ()).

Όπως ίσως έχετε παρατηρήσει, Ισχυρό Tokenizer εφαρμόζει το Απαρίθμηση διεπαφή, εφαρμόζοντας έτσι το hasMoreElements () και επόμενο στοιχείο () μεθόδους που απλώς αναθέτουν την κλήση στο hasMoreTokens () και nextToken (), αντίστοιχα. (Με την εφαρμογή του Απαρίθμηση διεπαφή, Ισχυρό Tokenizer γίνεται συμβατό με την έκδοση StringTokenizerΑς δούμε ένα παράδειγμα. Ας πούμε ότι η συμβολοσειρά εισόδου είναι "γεια, Σήμερα ,,, \" Είμαι \ ", πρόκειται να ,,, \" αγορά, ένα, βιβλίο \ "" και ο οριοθέτης είναι ,. Αυτή η συμβολοσειρά, όταν ορίζονται οι τιμές επιστροφής, όπως φαίνεται στον Πίνακα 1:

Πίνακας 1: Τιμές που επιστρέφονται από Tokenized String
ΤύποςΑριθμός κουπονιώνΔιακριτικά

StringTokenizer

(bReturnTokens = true)

19γεια:,: Σήμερα:,:,:,: "I:,: am":,: going to:,:,:,: "buy:,: a:,: book" (εδώ ο χαρακτήρας : διαχωρίζει τα διακριτικά)

Ισχυρό Tokenizer

(bReturnTokens = true)

13γεια:,: Σήμερα:,: "": "": Εγώ, είμαι:,: πηγαίνοντας σε:,: "": "": αγοράστε ένα βιβλίο (όπου "" σημαίνει συμβολοσειρά μήκους 0)

Ισχυρό Tokenizer

(bReturnTokens = false)

9γεια: Σήμερα: "": "": Είμαι: πρόκειται: "": "": αγοράστε ένα βιβλίο

Η συμβολοσειρά εισόδου περιέχει 11 κόμμα (,) χαρακτήρες, από τους οποίους τρεις βρίσκονται εντός των υποστρωμάτων και τέσσερις εμφανίζονται διαδοχικά (ως Σήμερα,,, κάνει δύο διαδοχικές εμφανίσεις κόμμα, το πρώτο είναι κόμμα Σήμεραοριοθέτης). Εδώ είναι η λογική για τον υπολογισμό του αριθμού των διακριτικών στο Ισχυρό Tokenizer υπόθεση:

  1. Σε περίπτωση που bReturnTokens = true, πολλαπλασιάστε τον αριθμό των οριοθετών εντός των υποστρωμάτων με 2 και αφαιρέστε το ποσό από το πραγματικό σύνολο για να λάβετε τον αριθμό των διακριτικών. Ο λόγος είναι, για το υπόστρωμα "αγοράστε ένα βιβλίο", StringTokenizer θα επιστρέψει πέντε διακριτικά (δηλαδή, αγοράστε:,: a:,: βιβλίο), ενώ Ισχυρό Tokenizer θα επιστρέψει ένα διακριτικό (δηλαδή, αγοράστε ένα βιβλίο). Η διαφορά είναι τέσσερα (δηλαδή, 2 * αριθμός οριοθετών εντός του υποστρώματος). Αυτός ο τύπος ισχύει για κάθε υπόστρωμα που περιέχει οριοθέτες. Λάβετε υπόψη την ειδική περίπτωση όπου το ίδιο το διακριτικό ισούται με τον οριοθέτη. Αυτό δεν πρέπει να μειώσει την τιμή μέτρησης.
  2. Ομοίως, για την περίπτωση του bReturnTokens = λάθος, αφαιρέστε την τιμή της έκφρασης [συνολικά οριοθέτες (11) - διαδοχικά οριοθέτες (4) + αριθμός οριοθετών εντός των υποστρωμάτων (3)] από το πραγματικό σύνολο (19) για να λάβετε τον αριθμό των διακριτικών. Δεδομένου ότι δεν επιστρέφουμε τους οριοθέτες σε αυτήν την περίπτωση, αυτοί (χωρίς να εμφανίζονται διαδοχικά ή μέσα σε υποστρώματα) δεν μας βοηθούν και η παραπάνω φόρμουλα μας δίνει τον συνολικό αριθμό των κουπονιών (9).

Θυμηθείτε αυτούς τους δύο τύπους, οι οποίοι είναι η καρδιά του Ισχυρό Tokenizer. Αυτοί οι τύποι λειτουργούν για όλες σχεδόν τις αντίστοιχες περιπτώσεις. Ωστόσο, εάν έχετε πιο περίπλοκες απαιτήσεις που δεν είναι κατάλληλες για αυτούς τους τύπους, τότε πρέπει να λάβετε υπόψη διάφορα παραδείγματα για να αναπτύξετε τη δική σας φόρμουλα πριν προχωρήσετε στην κωδικοποίηση.

 // ελέγξτε αν ο οριοθέτης βρίσκεται εντός ενός υποσυστήματος για (int i = 1; i

ο nextToken () μέθοδος παίρνει μάρκες χρησιμοποιώντας StringTokenizer.nextToken, και ελέγχει για τον χαρακτήρα διπλού εισαγωγικού στο διακριτικό. Εάν η μέθοδος εντοπίσει αυτούς τους χαρακτήρες, παίρνει περισσότερα διακριτικά έως ότου δεν βρει κανένα με διπλό εισαγωγικό. Αποθηκεύει επίσης το διακριτικό σε μια μεταβλητή (sPrevToken; δείτε τον πηγαίο κώδικα) για τον έλεγχο διαδοχικών εμφανίσεων οριοθέτη. Αν nextToken () βρίσκει διαδοχικά διακριτικά που είναι ίδια με τον οριοθέτη και μετά επιστρέφει "" (συμβολοσειρά με μήκος 0) ως διακριτικό.

Ομοίως, το hasMoreTokens () Η μέθοδος ελέγχει εάν ο αριθμός των διακριτικών που έχουν ήδη ζητηθεί είναι μικρότερος από τον συνολικό αριθμό των διακριτικών.

Εξοικονομήστε χρόνο ανάπτυξης

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

Ο Bhabani Padhi είναι αρχιτέκτονας και προγραμματιστής Java που εργάζεται επί του παρόντος στην ανάπτυξη εφαρμογών Ιστού και επιχειρήσεων χρησιμοποιώντας τεχνολογία Java στο UniteSys της Αυστραλίας. Προηγουμένως εργάστηκε στην Baltimore Technologies της Αυστραλίας στην ανάπτυξη προϊόντων ηλεκτρονικής ασφάλειας και στο Fujitsu της Αυστραλίας σε ένα έργο ανάπτυξης διακομιστή EJB. Τα ενδιαφέροντα του Bhabani περιλαμβάνουν κατανεμημένη πληροφορική, κινητές συσκευές και ανάπτυξη εφαρμογών Ιστού χρησιμοποιώντας τεχνολογία Java.

Μάθετε περισσότερα σχετικά με αυτό το θέμα

  • Λάβετε τον πηγαίο κώδικα για αυτήν τη συμβουλή

    //images.techhive.com/downloads/idge/imported/article/jvw/2001/06/powerfultokenizer.java

  • Για περισσότερες πληροφορίες σχετικά με το BreakIterator

    //java.sun.com/products/jdk/1.2/docs/api/java/text/BreakIterator.html

  • Δείτε όλα τα προηγούμενα Συμβουλές Java και υποβάλετε το δικό σας

    //www.javaworld.com/javatips/jw-javatips.index.html

  • Για περισσότερα Εισαγωγικό επίπεδο άρθρα, επίσκεψη JavaWorld 'Τοπ Ευρετήριο

    //www.javaworld.com/javaworld/topicalindex/jw-ti-introlevel.html

  • Μάθετε Java από την αρχή προς τα πάνω JavaWorld 'μικρό Java 101 στήλη

    //www.javaworld.com/javaworld/topicalindex/jw-ti-java101.html

  • Οι ειδικοί της Java απαντούν στις πιο δύσκολες ερωτήσεις σας στο Java JavaWorld 'μικρό Ε & Α Java στήλη

    //www.javaworld.com/javaworld/javaqa/javaqa-index.html

  • Εγγραφείτε στο JavaWorld αυτήν την εβδομάδα δωρεάν εβδομαδιαίο ενημερωτικό δελτίο ηλεκτρονικού ταχυδρομείου για να μάθετε τι νέο υπάρχει JavaWorld

    //www.idg.net/jw-subscribe

Αυτή η ιστορία, "Συμβουλή Java 112: Βελτίωση συμβολισμού συμβολοσειρών πλούσιων σε πληροφορίες" δημοσιεύθηκε αρχικά από την JavaWorld