JavaRush /Java Blog /Random-ID /String di Java (kelas java.lang.String)
Viacheslav
Level 3

String di Java (kelas java.lang.String)

Dipublikasikan di grup Random-ID

Perkenalan

Jalan seorang programmer adalah proses yang kompleks dan panjang. Dan dalam kebanyakan kasus, ini dimulai dengan program yang menampilkan Hello World di layar. Java tidak terkecuali (lihat Pelajaran: Aplikasi "Halo Dunia!" ). Seperti yang bisa kita lihat, pesan tersebut di-output menggunakan. System.out.println("Hello World!"); Jika Anda melihat Java API, metode System.out.println menggunakan String sebagai parameter input . Jenis data ini akan dibahas.

String sebagai rangkaian karakter

Sebenarnya String yang diterjemahkan dari bahasa Inggris adalah string. Benar, tipe String mewakili string teks. Apa itu string teks? String teks adalah semacam urutan karakter yang mengikuti satu sama lain. Simbolnya adalah arang. Urutan – urutan. Jadi ya, benar sekali, String adalah implementasi dari java.lang.CharSequence. Dan jika Anda melihat ke dalam kelas String itu sendiri, maka di dalamnya tidak ada yang lebih dari sebuah array karakter: private final char value[]; Ia memiliki java.lang.CharSequencekontrak yang cukup sederhana:
String di Java (kelas java.lang.String) - 1
Kami memiliki metode untuk mendapatkan jumlah elemen, mendapatkan elemen tertentu dan mendapatkan satu set elemen + metode toString itu sendiri, yang akan mengembalikan ini) Lebih menarik untuk memahami metode yang datang kepada kami di Java 8, dan ini adalah : chars()dan codePoints() Ingat dari Tutorial dari Oracle “ Primitive Data” Types " bahwa char adalah single 16-bit Unicode character. Artinya, pada dasarnya char hanyalah tipe setengah ukuran int (32 bit) yang mewakili angka dari 0 hingga 65535 (lihat nilai desimal dalam Tabel ASCII ). Artinya, jika kita mau, kita bisa merepresentasikan char sebagai int. Dan Java 8 memanfaatkan ini. Dimulai dengan Java versi 8, kami memiliki IntStream - aliran untuk bekerja dengan int primitif. Oleh karena itu, di charSequence dimungkinkan untuk mendapatkan IntStream yang mewakili karakter atau codePoints. Sebelum kita membahasnya, kita akan melihat contoh yang menunjukkan kemudahan pendekatan ini. Mari gunakan kompiler java online Tutorialspoint dan jalankan kodenya:
public static void main(String []args){
        String line = "aaabccdddc";
        System.out.println( line.chars().distinct().count() );
}
Kini Anda bisa mendapatkan sejumlah simbol unik dengan cara sederhana ini.

Titik Kode

Jadi, kita melihat tentang karakter. Sekarang tidak jelas apa jenis poin kode ini. Konsep codePoint muncul karena ketika Java muncul, 16 bit (setengah int) sudah cukup untuk mengkodekan sebuah karakter. Oleh karena itu, char di java direpresentasikan dalam format UTF-16 (spesifikasi "Unicode 88"). Belakangan muncul Unicode 2.0 yang konsepnya merepresentasikan karakter sebagai pasangan pengganti (2 karakter). Hal ini memungkinkan kami untuk memperluas jangkauan nilai yang mungkin ke nilai int. Untuk detail selengkapnya, lihat stackoverflow: " Membandingkan karakter dengan titik kode? " UTF-16 juga disebutkan dalam JavaDoc untuk Character . Di sana, di JavaDoc, dikatakan bahwa: 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). Cukup sulit (dan mungkin bahkan tidak mungkin) untuk mereproduksi ini dalam abjad standar. Namun simbolnya tidak diakhiri dengan huruf dan angka. Di Jepang mereka menemukan sesuatu yang sangat sulit untuk dikodekan seperti emoji – bahasa ideogram dan emotikon. Ada artikel menarik tentang ini di Wikipedia: “ Emoji ”. Mari kita cari contoh emoji, misalnya ini: “ Emoji Hantu ”. Seperti yang bisa kita lihat, codePoint yang sama bahkan ditunjukkan di sana (nilai = U+1F47B). Itu ditunjukkan dalam format heksadesimal. Jika kita mengkonversi ke angka desimal, kita mendapatkan 128123. Ini lebih dari 16 bit yang diperbolehkan (yaitu lebih dari 65535). Mari kita salin:
String di Java (kelas java.lang.String) - 2
Sayangnya, platform JavaRush tidak mendukung karakter seperti itu dalam teks. Oleh karena itu, pada contoh di bawah ini Anda perlu memasukkan nilai ke dalam String. Oleh karena itu, sekarang kita akan memahami tes sederhana:
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
}
Seperti yang Anda lihat, dalam hal ini 1 codePoint berlaku untuk 2 karakter. Inilah keajaibannya.

Karakter

Seperti yang kita lihat di atas, String di Java terdiri dari char. Tipe primitif memungkinkan Anda menyimpan nilai, tetapi pembungkus java.lang.Charactertipe primitif memungkinkan Anda melakukan banyak hal berguna dengan simbol ini. Misalnya, kita dapat mengubah string menjadi huruf besar:
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));
}
Nah, berbagai hal menariknya: isAlphabetic(), isLetter(), isSpaceChar(), isDigit(), isUpperCase(), isMirrored()(misalnya tanda kurung. '(' mempunyai bayangan cermin ')').

Kolam Tali

String di Java tidak dapat diubah, yaitu konstan. Hal ini juga ditunjukkan dalam JavaDoc dari kelas java.lang.String itu sendiri . Kedua, dan juga sangat penting, string dapat ditentukan sebagai literal:
String literalString = "Hello, World!";
String literalString = "Hello, World!";
Artinya, setiap string yang dikutip, sebagaimana dinyatakan di atas, sebenarnya adalah sebuah objek. Dan ini menimbulkan pertanyaan - jika kita menggunakan string begitu sering dan seringkali sama (misalnya, teks “Error” atau “Successful”), adakah cara untuk memastikan bahwa string tidak dibuat setiap saat? Omong-omong, kami masih memiliki Maps, yang kuncinya bisa berupa string. Maka kita pasti tidak bisa membuat string yang sama menjadi objek yang berbeda, jika tidak, kita tidak akan bisa mendapatkan objek tersebut dari Map. Pengembang Java berpikir, berpikir, dan menghasilkan String Pool. Ini adalah tempat penyimpanan string, Anda bisa menyebutnya cache string. Tidak semua baris itu sendiri berakhir di sana, tetapi hanya baris yang ditentukan dalam kode secara literal. Anda dapat menambahkan sendiri garis ke kumpulan, tetapi akan dibahas lebih lanjut nanti. Jadi, di memori kita memiliki cache ini di suatu tempat. Sebuah pertanyaan yang wajar: di manakah letak kolam ini? Jawabannya dapat ditemukan di stackoverflow: “ Di mana kumpulan konstanta String Java berada, heap atau stack? " Itu terletak di memori Heap, di area kumpulan konstan waktu proses khusus. Kumpulan konstanta Runtime dialokasikan ketika kelas atau antarmuka dibuat oleh mesin virtual dari area metode - area khusus di Heap yang dapat diakses oleh semua thread di dalam Mesin Virtual Java. Apa yang diberikan String pool kepada kita? Ini mempunyai beberapa keuntungan:
  • Objek dengan tipe yang sama tidak akan dibuat
  • Perbandingan dengan referensi lebih cepat dibandingkan perbandingan karakter demi karakter melalui persamaan
Namun bagaimana jika kita ingin memasukkan objek yang dibuat ke dalam cache ini? Kemudian, kita memiliki metode khusus: String.intern Metode ini menambahkan string ke String Pool. Perlu dicatat bahwa ini bukan hanya semacam cache dalam bentuk array (seperti untuk Integer). Metode magang ditetapkan sebagai "asli". Ini berarti bahwa metode itu sendiri diimplementasikan dalam bahasa lain (kebanyakan C++). Dalam kasus metode dasar Java, berbagai optimasi lainnya dapat diterapkan pada metode tersebut di tingkat JVM. Secara umum, keajaiban akan terjadi di sini. Menarik sekali membaca postingan tentang magang berikut ini: https://habr.com/post/79913/#comment_2345814 Dan sepertinya itu ide yang bagus. Namun bagaimana dampaknya terhadap kita? Tapi itu benar-benar akan berdampak)
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal");
    System.out.println(test == test2);
}
Seperti yang Anda lihat, garis-garisnya sama, tetapi hasilnya salah. Dan semua itu karena == membandingkan bukan berdasarkan nilai, tetapi berdasarkan referensi. Dan inilah cara kerjanya:
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal").intern();
    System.out.println(test == test2);
}
Perhatikan saja bahwa kami masih akan membuat String baru. Artinya, magang akan mengembalikan kita sebuah String dari cache, tetapi String asli yang kita cari di cache akan dibuang untuk dibersihkan, karena tidak ada orang lain yang tahu tentang dia. Ini jelas merupakan konsumsi sumber daya yang tidak perlu =( Oleh karena itu, Anda harus selalu membandingkan string menggunakan yang sama untuk menghindari kesalahan yang tiba-tiba dan sulit dideteksi sebanyak mungkin.
public static void main(String[] args) {
    String test = "literal";
    String test2 = new String("literal").intern();
    System.out.println(test.equals(test2));
}
Equals melakukan perbandingan string karakter demi karakter.

Rangkaian

Seingat kita, garis bisa ditambahkan. Dan seperti yang kita ingat, string kita tidak dapat diubah. Jadi bagaimana cara kerjanya? Benar sekali, baris baru dibuat, yang terdiri dari simbol-simbol objek yang ditambahkan. Ada jutaan versi tentang cara kerja plus penggabungan. Beberapa orang berpikir bahwa akan ada objek baru setiap saat, yang lain berpikir akan ada sesuatu yang lain. Tapi hanya satu orang yang mungkin benar. Dan seseorang itu adalah kompiler javac. Mari gunakan layanan kompiler online dan jalankan:
public class HelloWorld {

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

}
Sekarang mari simpan ini sebagai arsip zip, ekstrak ke direktori dan jalankan: javap –c HelloWorld Dan di sini kita menemukan semuanya:
String di Java (kelas java.lang.String) - 3
Dalam satu loop, tentu saja, lebih baik melakukan penggabungan melalui StringBuilder sendiri. Dan bukan karena semacam keajaiban, tetapi agar StringBuilder dibuat sebelum siklus, dan dalam siklus itu sendiri hanya penambahan yang terjadi. Ngomong-ngomong, ada hal menarik lainnya di sini. Ada artikel bagus: “ Pemrosesan String di Java. Bagian I: String, StringBuffer, StringBuilder ." Banyak informasi berguna di komentar. Misalnya, ditentukan bahwa saat menggabungkan tampilan, new StringBuilder().append()...toString()pengoptimalan intrinsik berlaku, diatur oleh opsi -XX:+OptimizeStringConcat, yang diaktifkan secara default. intrinsik - diterjemahkan sebagai "internal". JVM menangani hal-hal seperti itu dengan cara khusus, memprosesnya sebagai Asli, hanya saja tanpa biaya tambahan JNI. Baca selengkapnya: " Metode Intrinsik di HotSpot VM ".

StringBuilder dan StringBuffer

Seperti yang kita lihat di atas, StringBuilder adalah alat yang sangat berguna. String tidak dapat diubah, mis. kekal. Dan saya ingin melipatnya. Oleh karena itu, kita diberikan 2 kelas untuk membantu kita: StringBuilder dan StringBuffer. Perbedaan utama antara keduanya adalah StringBuffer diperkenalkan di JDK1.0, sedangkan StringBuilder hadir di Java 1.5 sebagai versi StringBuffer yang tidak disinkronkan untuk menghilangkan peningkatan overhead dari sinkronisasi metode yang tidak perlu. Kedua kelas ini merupakan implementasi dari kelas abstrak AbstrakStringBuilder - Urutan karakter yang bisa berubah. Array pesona disimpan di dalamnya, yang diperluas sesuai dengan aturan: value.length * 2 + 2. Secara default, ukuran (kapasitas) StringBuilder adalah 16.

Sebanding

Senarnya sebanding, mis. menerapkan metode bandingkanTo. Hal ini dilakukan dengan menggunakan perbandingan karakter demi karakter. Menariknya, panjang minimum dipilih dari dua string dan sebuah loop dieksekusi di atasnya. Oleh karena itu, CompareTo akan mengembalikan selisih antara nilai int dari karakter pertama yang tidak cocok hingga panjang string terkecil, atau mengembalikan selisih antara panjang string jika semua karakter cocok dalam panjang string minimum. Perbandingan ini disebut “leksikografis”.

Bekerja dengan String Java

String memiliki banyak metode yang berguna:
String di Java (kelas java.lang.String) - 4
Ada banyak tugas untuk bekerja dengan string. Misalnya saja pada Coding Bat . Ada juga kursus di coursera: " Algoritma pada String ".

Kesimpulan

Bahkan gambaran singkat tentang kelas ini memakan banyak ruang. Dan bukan itu saja. Saya sangat merekomendasikan menonton laporan dari JPoint 2015: Alexei Shipilev - Katekismus java.lang.String
#Viacheslav
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION