JavaRush /Java Blog /Random-TL /Mga String sa Java (class java.lang.String)

Mga String sa Java (class java.lang.String)

Nai-publish sa grupo

Panimula

Ang landas ng isang programmer ay isang kumplikado at mahabang proseso. At sa karamihan ng mga kaso nagsisimula ito sa isang programa na nagpapakita ng Hello World sa screen. Ang Java ay walang pagbubukod (tingnan ang Aralin: Ang "Hello World!" Application ). Tulad ng nakikita natin, ang mensahe ay output gamit ang System.out.println("Hello World!"); Kung titingnan mo ang Java API, ang System.out.println na pamamaraan ay tumatagal ng String bilang isang parameter ng input . Tatalakayin ang ganitong uri ng datos.

String bilang isang pagkakasunod-sunod ng mga character

Sa totoo lang, ang String na isinalin mula sa English ay isang string. Tama, ang uri ng String ay kumakatawan sa isang string ng teksto. Ano ang text string? Ang text string ay ilang uri ng nakaayos na pagkakasunud-sunod ng mga character na sumusunod sa isa't isa. Ang simbolo ay char. Pagkakasunod-sunod. Kaya oo, ganap na tama, ang String ay isang pagpapatupad ng java.lang.CharSequence. At kung titingnan mo ang loob mismo ng String class, sa loob nito ay walang iba kundi isang hanay ng mga karakter: private final char value[]; Mayroon itong java.lang.CharSequencemedyo simpleng kontrata:
Mga String sa Java (class java.lang.String) - 1
Mayroon kaming isang pamamaraan para sa pagkuha ng bilang ng mga elemento, pagkuha ng isang tiyak na elemento at pagkuha ng isang hanay ng mga elemento + ang toString na pamamaraan mismo, na ibabalik ito) Mas kawili-wiling maunawaan ang mga pamamaraan na dumating sa amin sa Java 8, at ito ay : chars()at codePoints() Alalahanin mula sa Tutorial mula sa Oracle “ Primitive Data” Types " na ang char ay single 16-bit Unicode character. Ibig sabihin, mahalagang char ay isang uri lamang na kalahati ng laki ng isang int (32 bits) na kumakatawan sa mga numero mula 0 hanggang 65535 (tingnan ang mga decimal values sa Talahanayan ng ASCII ). Iyon ay, kung nais natin, maaari nating i-represent ang char bilang int. At sinamantala ito ng Java 8. Simula sa bersyon 8 ng Java, mayroon kaming IntStream - isang stream para sa pagtatrabaho sa mga primitive na ints. Samakatuwid, sa charSequence posibleng makakuha ng IntStream na kumakatawan sa alinman sa mga char o codePoints. Bago tayo magpatuloy sa kanila, makakakita tayo ng isang halimbawa upang ipakita ang kaginhawahan ng diskarteng ito. Gamitin natin ang Tutorialspoint online java compiler at i-execute ang code:
public static void main(String []args){
        String line = "aaabccdddc";
        System.out.println( line.chars().distinct().count() );
}
Makakakuha ka na ngayon ng ilang natatanging simbolo sa simpleng paraan na ito.

CodePoints

Kaya, nakita namin ang tungkol sa mga karakter. Ngayon ay hindi malinaw kung anong uri ng mga punto ng code ang mga ito. Lumitaw ang konsepto ng codePoint dahil noong lumitaw ang Java, sapat na ang 16 bits (kalahating int) para mag-encode ng isang character. Samakatuwid, ang char sa java ay kinakatawan sa format na UTF-16 ("Unicode 88" na detalye). Nang maglaon, lumitaw ang Unicode 2.0, na ang konsepto ay kumakatawan sa isang karakter bilang isang kahalili na pares (2 character). Nagpahintulot ito sa amin na palawakin ang hanay ng mga posibleng halaga sa isang int na halaga. Para sa higit pang mga detalye, tingnan ang stackoverflow: " Paghahambing ng isang char sa isang code-point? " Ang UTF-16 ay binanggit din sa JavaDoc para sa Character . Doon, sa JavaDoc, sinasabi na: 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). Medyo mahirap (at marahil ay imposible pa) na kopyahin ito sa karaniwang mga alpabeto. Ngunit ang mga simbolo ay hindi nagtatapos sa mga titik at numero. Sa Japan nakaisip sila ng isang bagay na napakahirap i-encode bilang emoji - ang wika ng mga ideogram at emoticon. Mayroong isang kawili-wiling artikulo tungkol dito sa Wikipedia: " Emoji ". Maghanap tayo ng halimbawa ng emoji, halimbawa ito: “ Emoji Ghost ”. Tulad ng nakikita natin, ang parehong codePoint ay ipinahiwatig doon (halaga = U+1F47B). Ito ay ipinahiwatig sa hexadecimal na format. Kung magko-convert tayo sa isang decimal na numero, makakakuha tayo ng 128123. Ito ay higit sa 16 bits allow (i.e. higit sa 65535). kopyahin natin ito:
Mga String sa Java (class java.lang.String) - 2
Sa kasamaang palad, hindi sinusuportahan ng JavaRush platform ang mga naturang character sa text. Samakatuwid, sa halimbawa sa ibaba kakailanganin mong magpasok ng isang halaga sa String. Samakatuwid, ngayon mauunawaan natin ang isang simpleng pagsubok:
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
}
Tulad ng nakikita mo, sa kasong ito, ang 1 codePoint ay napupunta para sa 2 character. Ito ang magic.

karakter

Tulad ng nakita natin sa itaas, ang Strings sa Java ay binubuo ng char. Ang isang primitive na uri ay nagbibigay-daan sa iyo na mag-imbak ng isang halaga, ngunit ang isang wrapper java.lang.Charactersa isang primitive na uri ay nagbibigay-daan sa iyo na gumawa ng maraming kapaki-pakinabang na bagay gamit ang simbolong ito. Halimbawa, maaari naming i-convert ang isang string sa uppercase:
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));
}
Well, iba't ibang mga kawili-wiling bagay: isAlphabetic(), isLetter(), isSpaceChar(), isDigit(), isUpperCase(), isMirrored()(halimbawa, mga bracket. '(' ay may salamin na imahe ')').

String Pool

Ang mga string sa Java ay hindi nababago, iyon ay, pare-pareho. Ito ay ipinahiwatig din sa JavaDoc ng java.lang.String class mismo . Pangalawa, at napakahalaga din, ang mga string ay maaaring tukuyin bilang mga literal:
String literalString = "Hello, World!";
String literalString = "Hello, World!";
Iyon ay, ang anumang naka-quote na string, tulad ng nakasaad sa itaas, ay talagang isang bagay. At ito ay nagtatanong - kung gumagamit tayo ng mga string nang napakadalas at madalas silang pareho (halimbawa, ang tekstong "Error" o "Matagumpay"), mayroon bang anumang paraan upang matiyak na ang mga string ay hindi nilikha sa bawat oras? Oo nga pala, mayroon pa kaming Maps, kung saan ang susi ay maaaring isang string. Kung gayon, tiyak na hindi tayo maaaring magkaroon ng parehong mga string sa magkaibang mga bagay, kung hindi, hindi natin makukuha ang bagay mula sa Map. Ang mga developer ng Java ay nag-isip, nag-isip at nakaisip ng String Pool. Ito ay isang lugar kung saan naka-imbak ang mga string, maaari mo itong tawaging isang string cache. Hindi lahat ng mga linya mismo ay napupunta doon, ngunit ang mga linya lamang na tinukoy sa code sa pamamagitan ng literal. Maaari kang magdagdag ng isang linya sa pool nang mag-isa, ngunit higit pa tungkol doon sa ibang pagkakataon. Kaya, sa memorya mayroon kaming cache na ito sa isang lugar. Isang patas na tanong: saan matatagpuan ang pool na ito? Ang sagot dito ay matatagpuan sa stackoverflow: “ Saan nakatira ang Java's String constant pool, ang heap o ang stack? " Ito ay matatagpuan sa Heap memory, sa isang espesyal na runtime constant pool area. Ang Runtime constant pool ay inilalaan kapag ang isang klase o interface ay ginawa ng virtual machine mula sa method area - isang espesyal na lugar sa Heap kung saan ang lahat ng mga thread sa loob ng Java Virtual Machine ay may access. Ano ang ibinibigay sa atin ng String pool? Ito ay may ilang mga pakinabang:
  • Ang mga bagay na may parehong uri ay hindi malilikha
  • Ang paghahambing sa pamamagitan ng sanggunian ay mas mabilis kaysa sa paghahambing ng character-by-character sa pamamagitan ng equals
Ngunit paano kung gusto nating ilagay ang nilikhang bagay sa cache na ito? Pagkatapos, mayroon kaming espesyal na paraan: String.intern Ang pamamaraang ito ay nagdaragdag ng string sa String Pool. Ito ay nagkakahalaga ng noting na ito ay hindi lamang isang uri ng cache sa anyo ng isang array (tulad ng para sa Integers). Ang intern na pamamaraan ay tinukoy bilang "katutubong". Nangangahulugan ito na ang pamamaraan mismo ay ipinatupad sa ibang wika (karamihan sa C++). Sa kaso ng mga pangunahing pamamaraan ng Java, ang iba't ibang mga pag-optimize ay maaaring ilapat sa mga ito sa antas ng JVM. Sa pangkalahatan, ang magic ay mangyayari dito. Nakakatuwang basahin ang sumusunod na post tungkol sa mga intern: https://habr.com/post/79913/#comment_2345814 At mukhang magandang ideya ito. Ngunit paano ito makakaapekto sa atin? Ngunit ito ay talagang magkakaroon ng epekto)
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal");
    System.out.println(test == test2);
}
Tulad ng nakikita mo, ang mga linya ay pareho, ngunit ang resulta ay mali. At lahat dahil == naghahambing hindi sa pamamagitan ng halaga, ngunit sa pamamagitan ng sanggunian. At ito ay kung paano ito gumagana:
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal").intern();
    System.out.println(test == test2);
}
Tandaan lamang na gagawa pa rin kami ng bagong String. Iyon ay, ibabalik sa amin ng intern ang isang String mula sa cache, ngunit ang orihinal na String na hinanap namin sa cache ay itatapon para sa paglilinis, dahil walang ibang nakakaalam tungkol sa kanya. Ito ay malinaw na isang hindi kinakailangang pagkonsumo ng mga mapagkukunan =( Samakatuwid, dapat mong palaging ihambing ang mga string gamit ang mga katumbas upang maiwasan ang biglaan at mahirap na makita ang mga error hangga't maaari.
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal").intern();
    System.out.println(test.equals(test2));
}
Ang Equals ay gumaganap ng paghahambing ng character-by-character na string.

Pagsasama-sama

Tulad ng naaalala natin, maaaring magdagdag ng mga linya. At gaya ng naaalala natin, ang ating mga string ay hindi nababago. Kaya paano ito gumagana kung gayon? Tama, isang bagong linya ang nilikha, na binubuo ng mga simbolo ng mga bagay na idinagdag. Mayroong isang milyong bersyon kung paano gumagana ang plus concatenation. Ang ilang mga tao ay nag-iisip na mayroong isang bagong bagay sa bawat oras, ang iba ay nag-iisip na may iba pa. Ngunit maaaring isang tao lamang ang tama. At ang isang tao ay ang javac compiler. Gamitin natin ang online compiler service at patakbuhin ang:
public class HelloWorld {

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

}
Ngayon, i-save natin ito bilang isang zip archive, i-extract ito sa isang direktoryo at i-execute: javap –c HelloWorld At dito natin malalaman ang lahat:
Mga String sa Java (class java.lang.String) - 3
Sa isang loop, siyempre, mas mahusay na gawin ang concatenation sa pamamagitan ng StringBuilder sa iyong sarili. At hindi dahil sa ilang uri ng magic, ngunit upang ang StringBuilder ay nilikha bago ang cycle, at sa cycle mismo ay nagaganap lamang ang append. Siyanga pala, may isa pang kawili-wiling bagay dito. Mayroong isang mahusay na artikulo: " Pagproseso ng String sa Java. Bahagi I: String, StringBuffer, StringBuilder ." Maraming kapaki-pakinabang na impormasyon sa mga komento. Halimbawa, tinukoy na kapag pinagsama-sama ang isang view, new StringBuilder().append()...toString()ang intrinsic na pag-optimize ay may bisa, na kinokontrol ng -XX:+OptimizeStringConcat na opsyon, na pinagana bilang default. intrinsic - isinalin bilang "panloob". Pinangangasiwaan ng JVM ang mga naturang bagay sa isang espesyal na paraan, pinoproseso ang mga ito bilang Katutubo, nang walang karagdagang gastos ng JNI. Magbasa pa: " Mga Intrinsic na Paraan sa HotSpot VM ".

StringBuilder at StringBuffer

Tulad ng nakita natin sa itaas, ang StringBuilder ay isang napaka-kapaki-pakinabang na tool. Ang mga string ay hindi nababago, ibig sabihin. hindi nababago. At gusto ko itong itiklop. Samakatuwid, binibigyan kami ng 2 klase upang matulungan kami: StringBuilder at StringBuffer. Ang pangunahing pagkakaiba sa pagitan ng dalawa ay ang StringBuffer ay ipinakilala sa JDK1.0, habang ang StringBuilder ay dumating sa java 1.5 bilang isang hindi naka-synchronize na bersyon ng StringBuffer upang maalis ang tumaas na overhead ng hindi kinakailangang paraan ng pag-synchronize. Pareho sa mga klase na ito ay mga pagpapatupad ng abstract class na AbstractStringBuilder - Isang nababagong pagkakasunud-sunod ng mga character. Isang hanay ng mga anting-anting ang nakaimbak sa loob, na pinalawak ayon sa panuntunan: value.length * 2 + 2. Bilang default, ang laki (kapasidad) ng StringBuilder ay 16.

Maihahambing

Ang mga string ay maihahambing, i.e. ipatupad ang compareTo method. Ginagawa ito gamit ang paghahambing ng character-by-character. Kapansin-pansin, ang pinakamababang haba ay pinili mula sa dalawang mga string at isang loop ay pinaandar sa ibabaw nito. Samakatuwid, ibabalik ng compareTo ang pagkakaiba sa pagitan ng mga int value ng unang hindi magkatugmang mga character hanggang sa pinakamaliit na haba ng string, o ibabalik ang pagkakaiba sa pagitan ng mga haba ng string kung ang lahat ng mga character ay tumutugma sa pinakamababang haba ng string. Ang paghahambing na ito ay tinatawag na "lexicographical".

Paggawa gamit ang Java Strings

Ang string ay may maraming kapaki-pakinabang na pamamaraan:
Mga String sa Java (class java.lang.String) - 4
Mayroong maraming mga gawain para sa pagtatrabaho sa mga string. Halimbawa, sa Coding Bat . Mayroon ding kurso sa coursera: " Algorithms on Strings ".

Konklusyon

Kahit na ang isang maikling pangkalahatang-ideya ng klase na ito ay tumatagal ng isang kahanga-hangang dami ng espasyo. At hindi lang iyon. Lubos kong inirerekumenda na panoorin ang ulat mula sa JPoint 2015: Alexey Shipilev - Catechism java.lang.String
#Viacheslav
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION