JavaRush /Java блогы /Random-KK /Java тіліндегі жолдар (Java.lang.String класы)
Viacheslav
Деңгей

Java тіліндегі жолдар (Java.lang.String класы)

Топта жарияланған

Кіріспе

Программисттің жолы күрделі және ұзақ процесс. Ал көп жағдайда ол экранда Hello World көрсететін бағдарламадан басталады. Java ерекшелік емес ( «Сәлем әлем!» қолданбасы сабағын қараңыз ). System.out.println("Hello World!"); Көріп отырғанымыздай, хабар Java API арқылы шығарылады , System.out.println әдісі жолды енгізу параметрі ретінде қабылдайды . Бұл деректер түрі талқыланады.

Жол таңбалар тізбегі ретінде

Шын мәнінде, ағылшын тілінен аударылған String - бұл жол. Дұрыс, String түрі мәтіндік жолды білдіреді. Мәтіндік жол дегеніміз не? Мәтін жолы – бір-бірінен кейін келетін таңбалардың реттелген тізбегі. Таңба – таңба. Тізбек – реттілік. Сонымен, иә, мүлдем дұрыс, String - іске асыру java.lang.CharSequence. Егер сіз String класының ішіне қарасаңыз, онда оның ішінде таңбалар массивінен басқа ештеңе жоқ: Оның өте қарапайым келісімшарты private final char value[]; бар :java.lang.CharSequence
Java тіліндегі жолдар (Java.lang.String класы) - 1
Бізде элементтер санын алу, белгілі бір элементті алу және элементтер жиынтығын алу әдісі бар + мұны қайтаратын toString әдісі) Java 8-де бізге келген әдістерді түсіну қызықтырақ және бұл : chars()және codePoints() Oracle оқулығынан еске түсіру « Primitive Data » Types « бұл таңба single 16-bit Unicode character. Яғни, шын мәнінде char 0-ден 65535-ке дейінгі сандарды көрсететін int өлшемінің жарты түрі ғана (32 бит) (ондық мәндерді қараңыз). ASCII кестесінде ) . Яғни, егер қаласақ, таңбаны int ретінде көрсете аламыз. Ал Java 8 мұны пайдаланды. Java-ның 8-нұсқасынан бастап бізде IntStream - қарабайыр инттермен жұмыс істеуге арналған ағын бар. Сондықтан charSequence ішінде таңбаларды немесе code нүктелерін көрсететін IntStream алуға болады. Оларға көшпес бұрын, біз осы тәсілдің ыңғайлылығын көрсететін мысалды көреміз. Tutorialspoint онлайн java компиляторын қолданып , codeты орындаймыз:
public static void main(String []args){
        String line = "aaabccdddc";
        System.out.println( line.chars().distinct().count() );
}
Енді осы қарапайым жолмен бірнеше бірегей таңбаларды алуға болады.

CodePoints

Сонымен, біз таңбалар туралы көрдік. Енді бұл қандай code нүктелері екені белгісіз. CodePoint концепциясы пайда болды, себебі Java пайда болған кезде символды codeтау үшін 16 бит (жарты инт) жеткілікті болды. Сондықтан java тіліндегі char UTF-16 пішімінде ұсынылған («Юниcode 88» спецификациясы). Кейінірек Юниcode 2.0 пайда болды, оның тұжырымдамасы кейіпкерді суррогат жұп (2 таңба) ретінде көрсету болды. Бұл мүмкін мәндер ауқымын int мәніне дейін кеңейтуге мүмкіндік берді. Қосымша мәліметтер алу үшін stackoverflow бөлімін қараңыз: " Символды code нүктесімен салыстыру керек пе? " UTF-16 таңбаға арналған JavaDoc бағдарламасында да айтылған . Онда JavaDoc-та былай делінген: In this representation, supplementary characters are represented as a pair of char values, the first from the high-surrogates range, (\uD800-\uDBFF), the second from the low-surrogates range (\uDC00-\uDFFF). Мұны стандартты алфавиттерде көшіру өте қиын (тіпті мүмкін емес). Бірақ таңбалар әріптермен және сандармен аяқталмайды. Жапонияда олар эмодзи ретінде codeтау қиын нәрсе ойлап тапты - идеограммалар мен эмотикондардың тілі. Википедияда бұл туралы қызықты мақала бар: « Эмодзи ». Эмодзилердің мысалын табайық, мысалы: « Эмодзи елесі ». Көріп отырғанымыздай, сол жерде бірдей codePoint көрсетілген (мән = U+1F47B). Ол он алтылық форматта көрсетілген. Ондық санға түрлендірсек, біз 128123 аламыз. Бұл рұқсат етілген 16 биттен көп (яғни 65535-тен көп). Оны көшіріп алайық:
Java тіліндегі жолдар (Java.lang.String класы) - 2
Өкінішке орай, JavaRush платформасы мәтіндегі мұндай таңбаларды қолдамайды. Сондықтан төмендегі мысалда Жолға мән енгізу керек. Сондықтан қазір біз қарапайым сынақты түсінеміз:
public static void main(String []args){
	    String emojiString = "Вставте сюда эмоджи через ctrl+v";
	    //На один emojiString приходится 2 чара (т.к. не влезает в 16 бит)
	    System.out.println(emojiString.codePoints().count()); //1
	    System.out.println(emojiString.chars().count()); //2
}
Көріп отырғаныңыздай, бұл жағдайда 1 codePoint 2 таңбаға арналған. Бұл сиқыр.

Кейіпкер

Жоғарыда көргеніміздей, Java тіліндегі жолдар таңбадан тұрады. Қарапайым тип мәнді сақтауға мүмкіндік береді, бірақ java.lang.Characterқарабайыр түрдің үстіндегі қаптама осы таңба арқылы көптеген пайдалы нәрселерді жасауға мүмкіндік береді. Мысалы, жолды бас әріпке түрлендіруге болады:
public static void main(String[] args) {
    String line = "организация объединённых наций";
    char[] chars = line.toCharArray();
    for (int i = 0; i < chars.length; i++) {
        if (i == 0 || chars[i - 1] == ' ') {
            chars[i] = Character.toUpperCase(chars[i]);
        }
    }
    System.out.println(new String(chars));
}
Ал, әртүрлі қызықты нәрселер: isAlphabetic(), isLetter(), isSpaceChar(), isDigit(), isUpperCase(), isMirrored()(мысалы, жақшалар. '(' айна бейнесі бар ')').

Жолдық бассейн

Java тіліндегі жолдар өзгермейді, яғни тұрақты. Бұл java.lang.String класының JavaDoc бағдарламасында да көрсетілген . Екіншіден, сонымен қатар өте маңызды, жолдарды литералдар ретінде көрсетуге болады:
String literalString = "Hello, World!";
String literalString = "Hello, World!";
Яғни, кез келген тырнақшаға алынған жол, жоғарыда айтылғандай, шын мәнінде an object болып табылады. Және бұл сұрақ туындайды - егер біз жолдарды жиі қолданатын болсақ және олар жиі бірдей болуы мүмкін болса (мысалы, «Қате» немесе «Сәтті» мәтіні), жолдардың әр уақытта жасалмайтынына көз жеткізудің қандай да бір жолы бар ма? Айтпақшы, бізде әлі де Карталар бар, мұнда кілт жол болуы мүмкін. Сонда бізде бірдей жолдар әртүрлі нысандар болуы мүмкін емес, әйтпесе Картадан нысанды ала алмаймыз. Java әзірлеушілері ойланып, ойланып, String Pool ойлап тапты. Бұл жолдар сақталатын орын, оны жолдық кэш деп атауға болады. Онда барлық жолдар аяқталмайды, тек codeта литерал арқылы көрсетілген жолдар ғана аяқталады. Бассейнге сызықты өзіңіз қоса аласыз, бірақ бұл туралы кейінірек. Сонымен, жадымызда бұл кэш бір жерде бар. Әділ сұрақ: бұл бассейн қайда орналасқан? Бұған жауапты stackoverflow арқылы табуға болады: “ Java жолының тұрақты пулы қайда тұрады, үйме немесе стек? " Ол үйме жадында, арнайы орындалу уақытының тұрақты пул аймағында орналасқан. Орындау уақыты тұрақты пулы класс немесе интерфейс виртуалды машина арқылы әдіс аймағынан жасалған кезде бөлінеді - Java виртуалды машинасының ішіндегі барлық ағындар қол жеткізе алатын үймедегі арнайы аймақ. String pool бізге не береді? Бұл бірнеше артықшылықтарға ие:
  • Бір типті нысандар жасалмайды
  • Анықтама бойынша салыстыру теңдік арқылы таңбалар бойынша салыстыруға қарағанда жылдамырақ
Бірақ егер біз жасалған нысанды осы кэшке салғымыз келсе ше? Содан кейін бізде арнайы әдіс бар: String.intern Бұл әдіс жолды жол пулына қосады. Айта кету керек, бұл массив түріндегі кэштің бір түрі ғана емес (бүтін сандар сияқты). Интерн әдісі «туған» деп көрсетілген. Бұл әдістің өзі басқа тілде (негізінен C++) жүзеге асырылатынын білдіреді. Негізгі Java әдістері жағдайында оларға JVM деңгейінде әртүрлі басқа оңтайландырулар қолданылуы мүмкін. Жалпы, мұнда сиқыр болады. Интерн туралы келесі жазбаны оқу қызықты: https://habr.com/post/79913/#comment_2345814 Бұл жақсы идея сияқты. Бірақ бұл бізге қалай әсер етеді? Бірақ бұл шынымен әсер етеді)
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal");
    System.out.println(test == test2);
}
Көріп отырғаныңыздай, сызықтар бірдей, бірақ нәтиже жалған болады. Мұның бәрі == мән бойынша емес, сілтеме бойынша салыстыратындықтан. Және бұл қалай жұмыс істейді:
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal").intern();
    System.out.println(test == test2);
}
Біз әлі де жаңа String жасайтынымызды ескеріңіз. Яғни, интерн бізге кэштен Жолды қайтарады, бірақ кэште біз іздеген бастапқы Жол тазалау үшін лақтырылады, өйткені ол туралы басқа ешкім білмейді. Бұл ресурстарды қажетсіз тұтыну екені анық =( Сондықтан кенеттен және мүмкіндігінше анықтау қиын қателерді болдырмау үшін әрқашан тең мәндерді пайдаланып жолдарды салыстыру керек.
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal").intern();
    System.out.println(test.equals(test2));
}
Equals таңба бойынша жолды салыстыруды орындайды.

Біріктіру

Естеріңізде болса, жолдарды қосуға болады. Ал біз есімізде, біздің жолдар өзгермейді. Сонда ол қалай жұмыс істейді? Дұрыс, қосылатын an objectілердің таңбаларынан тұратын жаңа жол құрылады. Плюс жалғауының миллиондаған нұсқасы бар. Біреулер әр кезде жаңа an object болады деп ойлайды, енді біреулер басқа нәрсе болады деп ойлайды. Бірақ бір адам ғана дұрыс болуы мүмкін. Және бұл біреу javac компиляторы. Онлайн компилятор қызметін пайдаланып , іске қосайық:
public class HelloWorld {

    public static void main(String[] args) {
        String helloMessage = "Hello, ";
        String target = "World";
        System.out.println(helloMessage + target);
    }

}
Енді оны zip мұрағат ретінде сақтап, оны каталогқа шығарып, орындаймыз: javap –c HelloWorld Міне, біз бәрін білеміз:
Java тіліндегі жолдар (Java.lang.String класы) - 3
Әрине, циклде StringBuilder арқылы біріктіруді өзіңіз жасаған дұрыс. Және қандай да бір сиқырдың арқасында емес, StringBuilder циклден бұрын жасалуы үшін және циклдің өзінде тек қосымша пайда болады. Айтпақшы, бұл жерде тағы бір қызық жайт бар. Керемет мақала бар: « Java-дағы жолды өңдеу. I бөлім: String, StringBuffer, StringBuilder ." Түсініктемелерде көптеген пайдалы ақпарат. new StringBuilder().append()...toString()Мысалы, көріністі біріктіру кезінде әдепкі бойынша қосылған -XX:+OptimizeStringConcat опциясы арқылы реттелетін ішкі оңтайландырудың жұмыс істейтіні көрсетілген . intrinsic - «ішкі» деп аударылады. JVM мұндай нәрселерді арнайы жолмен өңдейді, оларды Native ретінде өңдейді, тек JNI қосымша шығындарынсыз. Толығырақ: « HotSpot VM жүйесіндегі ішкі әдістер ».

StringBuilder және StringBuffer

Жоғарыда көргеніміздей, StringBuilder өте пайдалы құрал. Жолдар өзгермейді, яғни. өзгермейтін. Ал мен оны бүктегім келеді. Сондықтан бізге көмектесу үшін бізге 2 сынып беріледі: StringBuilder және StringBuffer. Екеуінің арасындағы негізгі айырмашылық StringBuffer JDK1.0 жүйесінде енгізілді, ал StringBuilder қажетсіз әдіс синхрондауының жоғарылаған үстеме шығындарын жою үшін StringBuffer бағдарламасының синхрондалмаған нұсқасы ретінде java 1.5-те келді. Бұл класстардың екеуі де AbstractStringBuilder абстрактілі класстың іске асырылуы болып табылады - өзгермелі таңбалар тізбегі. Шеберлердің жиымы ішінде сақталады, ол ережеге сәйкес кеңейтіледі: value.length * 2 + 2. Әдепкі бойынша StringBuilder өлшемі (сыйымдылығы) 16.

Салыстырмалы

Жолдар салыстырмалы, яғни. compareTo әдісін орындаңыз. Бұл таңбалар бойынша салыстыру арқылы жасалады. Бір қызығы, ең аз ұзындық екі жолдан таңдалады және оның үстіне цикл орындалады. Сондықтан, compareTo ең кіші жол ұзындығына дейінгі бірінші сәйкес келмейтін таңбалардың int мәндері арасындағы айырмашылықты қайтарады немесе барлық таңбалар жолдың ең аз ұзындығына сәйкес келсе, жол ұзындығы арасындағы айырмашылықты қайтарады. Бұл салыстыру «лексикографиялық» деп аталады.

Java жолдарымен жұмыс істеу

Жолдың көптеген пайдалы әдістері бар:
Java тіліндегі жолдар (Java.lang.String класы) - 4
Жолдармен жұмыс істеуге арналған көптеген тапсырмалар бар. Мысалы, Coding Bat туралы . Сондай-ақ курстар бойынша курс бар: « Жолдардағы алгоритмдер ».

Қорытынды

Бұл сыныпқа қысқаша шолу тіпті әсерлі кеңістікті алады. Бұл бәрі емес. Мен JPoint 2015 баяндамасын қарауды ұсынамын: Алексей Шипилев - Catechism java.lang.String
#Вячеслав
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION