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

Συγκρίσεις συμβολοσειρών στην Java

Στην Java, το Σειρά class ενσωματώνει μια σειρά από απανθρακώνω. Θεσω απλα, Σειρά είναι μια σειρά χαρακτήρων που χρησιμοποιούνται για τη σύνθεση λέξεων, προτάσεων ή οποιωνδήποτε άλλων δεδομένων θέλετε.

Το Encapsulation είναι μια από τις πιο ισχυρές έννοιες στον αντικειμενοστραφή προγραμματισμό Λόγω της ενθυλάκωσης, δεν χρειάζεται να γνωρίζετε πως λειτουργεί η κλάση String. απλά πρέπει να ξέρετε τι μεθόδους για χρήση στη διεπαφή του.

Όταν κοιτάς το Σειρά τάξη στην Java, μπορείτε να δείτε πώς ο πίνακας του απανθρακώνω είναι ενθυλακωμένο:

 δημόσια συμβολοσειρά (τιμή char []) {αυτό (τιμή, 0, value.length, null); } 

Για να κατανοήσετε καλύτερα την ενθυλάκωση, σκεφτείτε ένα φυσικό αντικείμενο: ένα αυτοκίνητο. Πρέπει να γνωρίζετε πώς λειτουργεί το αυτοκίνητο κάτω από την κουκούλα για να το οδηγήσετε; Φυσικά όχι, αλλά πρέπει να γνωρίζετε τι κάνουν οι διεπαφές του αυτοκινήτου: πράγματα όπως το γκάζι, τα φρένα και το τιμόνι. Κάθε μία από αυτές τις διεπαφές υποστηρίζει ορισμένες ενέργειες: επιτάχυνση, φρένο, στροφή αριστερά, στροφή δεξιά. Είναι το ίδιο στον αντικειμενοστρεφή προγραμματισμό.

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

 δημόσια συμβολοσειρά (αρχική συμβολοσειρά) {} δημόσια συμβολοσειρά (τιμή char [], int offset, int count) {} δημόσια συμβολοσειρά (int [] codePoints, int offset, int count) {} δημόσια συμβολοσειρά (byte byte [], int offset , int length, String charsetName) {} // Και ούτω καθεξής ... ... 

Αντί να προσπαθούμε να καταλάβουμε πώς το Σειρά τάξη λειτουργεί, αυτό το Java Challenger θα σας βοηθήσει να καταλάβετε τι το κάνει και πως για να το χρησιμοποιήσετε στον κωδικό σας.

Τι είναι μια πισίνα String;

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

Rafael Chinelato Del Nero

Αν και δημιουργήσαμε ένα Σειρά μεταβλητή για το Δούκας και JuggyΣειράs, μόνο δύο αντικείμενα δημιουργούνται και αποθηκεύονται στο σωρό μνήμης. Για απόδειξη, δείτε το ακόλουθο δείγμα κώδικα. (Θυμηθείτε ότι το «==Ο τελεστής στην Java χρησιμοποιείται για να συγκρίνει δύο αντικείμενα και να προσδιορίσει εάν είναι ίδια.)

 String juggy = "Juggy"; String anotherJuggy = "Juggy"; System.out.println (juggy == anotherJuggy); 

Αυτός ο κωδικός θα επιστρέψει αληθής γιατί τα δύο Σειράs στο ίδιο αντικείμενο στο Σειρά πισίνα. Οι αξίες τους είναι ίδιες.

Εξαίρεση: Ο «νέος» χειριστής

Τώρα κοιτάξτε αυτόν τον κώδικα - μοιάζει με το προηγούμενο δείγμα, αλλά υπάρχει μια διαφορά.

 String duke = νέα String ("duke"); String anotherDuke = new String ("duke"); System.out.println (duke == anotherDuke); 

Με βάση το προηγούμενο παράδειγμα, ίσως νομίζετε ότι αυτός ο κωδικός θα επιστρέψει αληθής, αλλά είναι στην πραγματικότητα ψευδής. Προσθήκη του νέος ο χειριστής αναγκάζει τη δημιουργία ενός νέου Σειρά στο σωρό της μνήμης. Έτσι, το JVM θα δημιουργήσει δύο διαφορετικά αντικείμενα.

Εγγενείς μέθοδοι

ΕΝΑ εγγενής μέθοδος Στην Java είναι μια μέθοδος που θα καταρτιστεί χρησιμοποιώντας τη γλώσσα C, συνήθως για τον χειρισμό της μνήμης και τη βελτιστοποίηση της απόδοσης.

String pools και η μέθοδος intern ()

Για να αποθηκεύσετε ένα Σειρά στο Σειρά πισίνα, χρησιμοποιούμε μια τεχνική που ονομάζεται Σειρά πρακτική. Εδώ μας λέει ο Javadoc για το κρατώ() μέθοδος:

 / ** * Επιστρέφει μια κανονική αναπαράσταση για το αντικείμενο συμβολοσειράς. * * Μια ομάδα συμβολοσειρών, αρχικά κενή, διατηρείται ιδιωτικά από το * class {@code String}. * * Όταν καλείται η μέθοδος intern, εάν η ομάδα περιέχει ήδη μια συμβολοσειρά * ίση με αυτό το αντικείμενο {@code String} όπως καθορίζεται από τη μέθοδο {@link #equals (Object)}, τότε η συμβολοσειρά από την ομάδα είναι * Επέστρεψαν. Διαφορετικά, αυτό το αντικείμενο {@code String} προστίθεται στην ομάδα * και επιστρέφεται μια αναφορά σε αυτό το αντικείμενο {@code String}. * * Ακολουθεί ότι για οποιεσδήποτε δύο συμβολοσειρές {@code s} και {@code t}, * {@code s.intern () == t.intern ()} είναι {@code true} * εάν και μόνο εάν { Το @code s.equals (t)} είναι {@code true}. * * Όλες οι κυριολεκτικές συμβολοσειρές και οι σταθερές εκφράσεις αξίας συμβολοσειράς είναι εσωτερικευμένες. Τα γράμματα συμβολοσειράς ορίζονται στην ενότητα 3.10.5 του * The Java ™ Language Specification. * * @ επιστρέφει μια συμβολοσειρά που έχει το ίδιο περιεχόμενο με αυτήν τη συμβολοσειρά, αλλά είναι εγγυημένη ότι προέρχεται από μια ομάδα μοναδικών συμβολοσειρών. * @jls 3.10.5 String Literals * / δημόσιος εγγενής String intern (); 

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

Τώρα, παρατηρήστε τι συμβαίνει όταν χρησιμοποιούμε το νέος λέξη-κλειδί για να αναγκάσει τη δημιουργία δύο Σειράμικρό:

 String duke = new String ("duke"); String duke2 = new String ("duke"); System.out.println (duke == duke2); // Το αποτέλεσμα θα είναι ψευδές εδώ System.out.println (duke.intern () == duke2.intern ()); // Το αποτέλεσμα θα ισχύει εδώ 

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

Ισούται με τη μέθοδο String

ο ισούται με () χρησιμοποιείται μέθοδος για την επαλήθευση εάν η κατάσταση των δύο τάξεων Java είναι η ίδια. Επειδή ισούται με () είναι από το Αντικείμενο τάξη, κάθε κλάση Java την κληρονομεί. Αλλά το ισούται με () Η μέθοδος πρέπει να παρακαμφθεί για να λειτουργήσει σωστά. Φυσικά, Σειρά παρακάμπτει ισούται με ().

Ρίξε μια ματιά:

 public boolean ισούται με (Object anObject) {if (this == anObject) {return true; } if (anObject instanceof String) {String aString = (String) anObject; if (coder () == aString.coder ()) {return isLatin1 (); StringLatin1.equals (τιμή, aString.value): StringUTF16.equals (τιμή, aString.value); }} επιστροφή false; } 

Όπως μπορείτε να δείτε, η κατάσταση του Σειρά η τιμή της τάξης πρέπει να είναι ισούται με () και όχι η αναφορά αντικειμένου. Δεν έχει σημασία αν η αναφορά αντικειμένου είναι διαφορετική. η κατάσταση του Σειρά θα συγκριθεί.

Οι πιο κοινές μέθοδοι συμβολοσειράς

Υπάρχει μόνο ένα τελευταίο πράγμα που πρέπει να γνωρίζετε πριν πάρετε το Σειρά πρόκληση σύγκρισης. Εξετάστε αυτές τις κοινές μεθόδους του Σειρά τάξη:

 // Αφαιρεί κενά από την περιγράμματα περιθωρίων () // Παίρνει ένα υπόστρωμα με υπόστρωμα ευρετηρίου (int beginIndex, int endIndex) // Επιστρέφει το μήκος χαρακτήρων του μήκους συμβολοσειράς () // Αντικαθιστά τη συμβολοσειρά, μπορεί να χρησιμοποιηθεί regex. substitAll (String regex, String Replacement) // Επαληθεύει εάν υπάρχει ένα καθορισμένο CharSequence στο String περιέχει (CharSequences) 

Πάρτε την πρόκληση σύγκρισης String!

Ας δοκιμάσουμε τι έχετε μάθει για το Σειρά τάξη σε μια γρήγορη πρόκληση.

Για αυτήν την πρόκληση, θα συγκρίνετε έναν αριθμό Σειράχρησιμοποιώντας τις έννοιες που έχουμε διερευνήσει. Κοιτάζοντας τον παρακάτω κώδικα, μπορείτε να προσδιορίσετε την τελική τιμή του καθενός Αποτελέσματα μεταβλητός?

 δημόσια τάξη ComparisonStringChallenge {public static void main (String ... doYourBest) {String result = ""; αποτέλεσμα + = "ισχυρό κώδικα" .trim () == "ισχυρό κώδικα"; "0": "1"; αποτέλεσμα + = "FlexibleCode" == "FlexibleCode"; "2": "3"; αποτέλεσμα + = νέα συμβολοσειρά ("doYourBest") == νέα συμβολοσειρά ("doYourBest"); "4": "5"; αποτέλεσμα + = νέα συμβολοσειρά ("noBugsProject"). Equals ("noBugsProject"); "6": "7"; αποτέλεσμα + = νέα συμβολοσειρά ("breakYourLimits"). intern () == new String ("breakYourLimits"). intern ()? "8": "9"; System.out.println (αποτέλεσμα); }} 

Ποια έξοδος αντιπροσωπεύει την τελική τιμή της μεταβλητής αποτελεσμάτων;

ΕΝΑ: 02468

σι: 12469

ντο: 12579

ρε: 12568

Ελέγξτε την απάντησή σας εδώ.

Τι συνέβη μόλις τώρα? Κατανόηση της συμπεριφοράς του String

Στην πρώτη γραμμή του κώδικα, βλέπουμε:

 αποτέλεσμα + = "ισχυρό κώδικα" .trim () == "ισχυρό κώδικα"; "0": "1"; 

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

Στη συνέχεια, βλέπουμε:

 αποτέλεσμα + = "FlexibleCode" == "FlexibleCode"; "2": "3"; 

Δεν υπάρχει μυστήριο εδώ, το Σειράείναι τα ίδια στο Σειρά πισίνα. Αυτή η σύγκριση επιστρέφει αληθής.

Στη συνέχεια, έχουμε:

 αποτέλεσμα + = νέα συμβολοσειρά ("doYourBest") == νέα συμβολοσειρά ("doYourBest"); "4": "5"; 

Χρησιμοποιώντας το νέος Η δεσμευμένη λέξη-κλειδί αναγκάζει τη δημιουργία δύο νέων Σειράs, είτε είναι ίσοι είτε όχι. Σε αυτήν την περίπτωση η σύγκριση θα είναι ψευδής ακόμα και αν το Σειρά οι τιμές είναι ίδιες.

Το επόμενο είναι:

 αποτέλεσμα + = νέα συμβολοσειρά ("noBugsProject"). Equals ("noBugsProject"); "6": "7"; 

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

Τέλος, έχουμε:

 αποτέλεσμα + = νέα συμβολοσειρά ("breakYourLimits"). intern () == new String ("breakYourLimits"). intern ()? "8": "9"; 

Όπως έχετε ξαναδεί, το κρατώ() μέθοδος βάζει το Σειρά στο Σειρά πισίνα. Και τα δυο Σειράs στο ίδιο αντικείμενο, οπότε σε αυτήν την περίπτωση η σύγκριση είναι αληθής.

Πρόκληση βίντεο! Συγκρίσεις συμβολοσειράς εντοπισμού σφαλμάτων

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

Συνηθισμένα λάθη με το Strings

Μπορεί να είναι δύσκολο να γνωρίζουμε αν δύο Σειράs δείχνουν προς το ίδιο αντικείμενο, ειδικά όταν το Σειράπεριέχουν την ίδια τιμή. Σας βοηθά να θυμάστε ότι χρησιμοποιώντας την δεσμευμένη λέξη-κλειδί νέος οδηγεί πάντα στη δημιουργία ενός νέου αντικειμένου στη μνήμη, ακόμα και αν οι τιμές είναι ίδιες.

Χρησιμοποιώντας Σειρά μεθόδους σύγκρισης Αντικείμενο οι αναφορές μπορεί επίσης να είναι δύσκολες. Το κλειδί είναι, εάν η μέθοδος αλλάξει κάτι στο Σειρά, οι αναφορές αντικειμένων θα είναι διαφορετικές.

Μερικά παραδείγματα για διευκρίνιση:

 System.out.println ("duke" .trim () == "duke" .trim ()) ;; 

Αυτή η σύγκριση θα ισχύει επειδή το τακτοποίηση() Η μέθοδος δεν δημιουργεί νέο Σειρά.

 System.out.println ("duke" .trim () == "duke" .trim ()); 

Σε αυτήν την περίπτωση, το πρώτο τακτοποίηση() μέθοδος θα δημιουργήσει ένα νέο Σειρά επειδή η μέθοδος θα εκτελέσει τη δράση της, έτσι οι αναφορές θα είναι διαφορετικές.

Τέλος, όταν τακτοποίηση() εκτελεί τη δράση του, δημιουργεί ένα νέο Σειρά:

 // Εφαρμογή της μεθόδου trim στο String class String new (Arrays.copyOfRange (val, index, index + len), LATIN1); 

Τι πρέπει να θυμάστε για το Strings

  • Σειράείναι αμετάβλητα, έτσι α ΣειράΗ κατάσταση δεν μπορεί να αλλάξει.
  • Για τη διατήρηση της μνήμης, το JVM διατηρεί Σειράs σε ένα Σειρά πισίνα. Όταν ένα νέο Σειρά δημιουργείται, το JVM ελέγχει την τιμή του και το δείχνει σε ένα υπάρχον αντικείμενο. Εάν δεν υπάρχει Σειρά με αυτήν την τιμή στην ομάδα, τότε το JVM δημιουργεί ένα νέο Σειρά.
  • Χρησιμοποιώντας το == τελεστής συγκρίνει την αναφορά αντικειμένου. Χρησιμοποιώντας το ισούται με () μέθοδος συγκρίνει την τιμή του Σειρά. Ο ίδιος κανόνας θα εφαρμοστεί σε όλα τα αντικείμενα.
  • Όταν χρησιμοποιείτε το νέος χειριστής, ένα νέο Σειρά θα δημιουργηθεί στο Σειρά πισίνα ακόμη και αν υπάρχει Σειρά με την ίδια τιμή.

 

Κλειδί απάντησης

Η απάντηση σε αυτόν τον αμφισβητία Java είναι η επιλογή D. Η έξοδος θα ήταν 12568.

Αυτή η ιστορία, "Σύγκριση χορδών στην Java" δημοσιεύθηκε αρχικά από το JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found