JavaRush /בלוג Java /Random-HE /שיטת charAt() ב-Java

שיטת charAt() ב-Java

פורסם בקבוצה
ישנן טכניקות בסיסיות רבות שאנו משתמשים בהן באופן קבוע מבלי לחשוב על כך. ובכן, מה אם תחשוב על זה ותראה איך מיישמים כמה שיטות פשוטות לכאורה? אני חושב שזה יעזור לנו להתקרב צעד אחד יותר לג'אווה) charAt() ב-Java - 1בואו נדמיין מצב שבו אנחנו צריכים לחלץ תו מסוים במחרוזת כלשהי. איך אנחנו יכולים לעשות את זה ב-Java? לדוגמה, על ידי קריאה ל- Java String charAt. charAt()נדבר על השיטה במאמר של היום.

תחביר

char charAt(int index)מחזירה את ערך ה-char במדד שצוין. המדד נע בין 0 ל- length()-1. כלומר, charהערך הראשון של הרצף הוא ב- index 0, הבא הוא ב- index 1וכו', כפי שקורה באינדקס של מערכים.

דוגמא

public static void main(String[] args) {
   System.out.print("JavaRush".charAt(0));
   System.out.print("JavaRush".charAt(1));
   System.out.print("JavaRush".charAt(2));
   System.out.print("JavaRush".charAt(3));
}
השורה הראשונה לוקחת את התו הראשון, השורה השנייה לוקחת את השני, וכן הלאה. מכיוון שלא println, אלא משמש כאן print, ללא שורה חדשה, נקבל את הפלט הבא לקונסולה:

Java
אם charהאינדקס הנתון מיוצג כ-Unicode, התוצאה של השיטה java charAt()תהיה התו שמייצג את ה-Unicode הזה:
System.out.println("J\u0061vaRush".charAt(1));
פלט מסוף:

a

מה זה "מתחת למכסה המנוע"

איך זה עובד, אתם שואלים? charAt() ב-Java - 2העובדה היא שכל אובייקט Stringמכיל מערך byteעם בתים של האלמנטים של מחרוזת נתונה:
private final byte[] value;
והנה השיטה עצמה chatAt:
public char charAt(int index) {
   if (isLatin1()) {
       return StringLatin1.charAt(value, index);
   } else {
       return StringUTF16.charAt(value, index);
   }
}
isLatin1- דגל המציין אם המחרוזת שלנו מכילה רק תווים לטיניים או לא. זה קובע איזו שיטה תיקרא הבאה.

isLatin1 = נכון

אם המחרוזת מכילה רק תווים לטיניים, שיטת charAtמחלקה סטטית נקראת StringLatin1:
public static char charAt(byte[] value, int index) {
   if (index < 0 || index >= value.length) {
       throw new StringIndexOutOfBoundsException(index);
   }
   return (char)(value[index] & 0xff);
}
השלב הראשון הוא לבדוק שהאינדקס הנכנס גדול מ-0 או שווה ל-0, ושהוא לא עובר את מערך הבתים הפנימי, ואם זה לא המקרה, אז נזרק חריג new StringIndexOutOfBoundsException(index). אם הבדיקות יעברו, אז האלמנט שאנחנו צריכים נלקח. בסוף אנחנו רואים:
  • &מרחיב לפעולה בינארית ל- bytebitwise
  • 0xffלא עושה כלום אבל &דורש ויכוח
  • (char)ממירה נתונים מטבלת ASCII לchar

isLatin1 = false

אם היו לנו לא רק תווים לטיניים, המחלקה תשמש StringUTF16והשיטה הסטטית שלה תיקרא:
public static char charAt(byte[] value, int index) {
   checkIndex(index, value);
   return getChar(value, index);
}
וזה בתורו קורא:
public static void checkIndex(int off, byte[] val) {
   String.checkIndex(off, length(val));
}
והוא מאציל לשיטה סטטית String:
static void checkIndex(int index, int length) {
   if (index < 0 || index >= length) {
       throw new StringIndexOutOfBoundsException("index " + index +
                                                 ", length " + length);
   }
}
כאן, למעשה, בודקים אם המדד תקף: שוב, האם הוא חיובי או אפס, והאם הוא לא חרג מגבולות המערך. אבל בכיתה StringUTF16בשיטה, charAtהקריאה למתודה השנייה תהיה מעניינת יותר:
static char getChar(byte[] val, int index) {
   assert index >= 0 && index < length(val) : "Trusted caller missed bounds check";
   index <<= 1;
   return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
                 ((val[index]   & 0xff) << LO_BYTE_SHIFT));
}
בואו נתחיל לנתח מה בעצם קורה כאן. השלב הראשון בתחילת השיטה הוא בדיקה נוספת לתקפות האינדקס. כדי להבין מה קורה לאחר מכן, עליך להבין: כאשר תו שאינו לטינית נכנס למערך value, הוא מיוצג על ידי שני בתים (שני תאי מערך). אם יש לנו מחרוזת של שני תווים קיריליים - "av", אז:
  • עבור 'a' זהו זוג בתים - 48 ו-4;
  • עבור 'in' - 50 ו-4.
כלומר, אם ניצור את המחרוזת "av", יהיה לה מערך value- {48, 4, 50, 4} למעשה, שיטה זו עובדת עם שני תאי מערך value. לכן, השלב הבא הוא מעבר index <<= 1;כדי להגיע ישירות לאינדקס של הביט הראשון של התו הרצוי במערך value. עכשיו נניח שיש לנו מחרוזת "абвг". ואז מערך הערכים ייראה כך: {48, 4, 49, 4, 50, 4, 51, 4}. אנו מבקשים את האלמנט השלישי של המחרוזת, ואז הייצוג הבינארי הוא 00000000 00000011. כאשר מוזז ב-1, נקבל 00000000 00000110, כלומר index = 6. כדי לרענן את הידע שלך על פעולות סיביות, אתה יכול לקרוא מאמר זה . charAt() ב-Java - 4אנו רואים גם כמה משתנים: HI_BYTE_SHIFT במקרה זה הוא 0. LO_BYTE_SHIFTבמקרה זה הוא 8. בשורה האחרונה של שיטה זו:
  1. אלמנט נלקח ממערך הערכים ומוזז בשיטת סיביות על ידי HI_BYTE_SHIFT, כלומר 0, תוך הגדלת index +1.

    בדוגמה עם המחרוזת "абвг", הביט השישי - 51 - יישאר כך, אבל באותו זמן האינדקס גדל ל-7.

  2. לאחר מכן, האלמנט הבא של המערך נלקח ומוזז בסיביות באותו אופן, אך ב-LO_BYTE_SHIFT, כלומר ב-8 סיביות.

    ואם היה לנו בייט 4, שיש לו ייצוג בינארי - 00000000 00000100, אז לאחר הזזה ב-8 סיביות יהיה לנו 00000100 00000000. אם זה מספר שלם - 1024.

  3. לאחר מכן, עבור שני הערכים הללו, בצע את הפעולה | (OR).

    ואם היו לנו בתים 51 ו-1024, שבייצוג בינארי נראה כמו 00000000 00110011 ו-00000100 00000000, אז אחרי הפעולה ORנקבל 00000100 00110011, כלומר המספר 1075.

    ובכן, בסופו של דבר, המספר 1075 מומר לסוג char, ובהמרה int -> char משתמשים בטבלת ASCII ובתוכה מתחת למספר 1075 יש את התו 'g'.

למעשה, כך אנו מקבלים 'g' כתוצאה מהשיטה charAt()בתכנות Java.
הערות
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION