Saya menggunakan variabel dengan banyak data di dalamnya, katakanlah String data
. Saya ingin menggunakan sebagian kecil dari string ini dengan cara berikut:
this.smallpart = data.substring(12,18);
Setelah beberapa jam melakukan debug (dengan visualizer memori) saya menemukan bahwa bidang objek smallpart
mengingat semua data dari data
, meskipun hanya berisi substring.
Ketika saya mengubah kode menjadi:
this.smallpart = data.substring(12,18)+"";
..masalah terselesaikan! Sekarang aplikasi saya menggunakan sangat sedikit memori sekarang!
Bagaimana mungkin? Adakah yang bisa menjelaskan ini? Saya pikir ini. Sebagian kecil terus merujuk pada data, tapi mengapa?
PEMBARUAN: Bagaimana saya bisa menghapus String besar itu? Apakah data = String baru (data.substring (0,100)) melakukan hal itu?
java
performance
string
memory
hsmit
sumber
sumber
new String(String)
; lihat stackoverflow.com/a/390854/8946 .Jawaban:
Melakukan hal berikut:
menciptakan objek String baru (lebih kecil), dan membuang referensi ke String yang dibuat oleh substring (), sehingga memungkinkan pengumpulan sampah ini.
Hal penting untuk disadari adalah
substring()
memberikan jendela ke String yang ada - atau lebih tepatnya, array karakter yang mendasari String asli. Karenanya ia akan menggunakan memori yang sama dengan String asli. Ini bisa menguntungkan dalam beberapa keadaan, tetapi bermasalah jika Anda ingin mendapatkan substring dan membuang String asli (seperti yang Anda temukan).Lihatlah metode substring () di sumber String JDK untuk info lebih lanjut.
EDIT: Untuk menjawab pertanyaan tambahan Anda, membangun sebuah String baru dari substring akan mengurangi konsumsi memori Anda, asalkan Anda membuang referensi ke String asli.
CATATAN (Jan 2013). Perilaku di atas telah berubah di Java 7u6 . Pola kelas terbang tidak lagi digunakan dan
substring()
akan berfungsi seperti yang Anda harapkan.sumber
String(String)
konstruktor (yaitu konstruktor String mengambil String sebagai input) berguna:new String(data.substring(x, y))
melakukan hal yang sama efektifnya dengan menambahkan""
, tetapi itu membuat maksudnya menjadi lebih jelas.value
atribut dari string asli. Saya pikir itu sebabnya referensi disimpan.Jika Anda melihat sumbernya
substring(int, int)
, Anda akan melihatnya kembali:dimana
value
aslinyachar[]
. Jadi Anda mendapatkan String baru tetapi dengan dasar yang samachar[]
.Saat kamu melakukan,
data.substring() + ""
Anda mendapatkan String baru dengan dasar yang baruchar[]
.Sebenarnya, use case Anda adalah satu-satunya situasi di mana Anda harus menggunakan
String(String)
konstruktor:sumber
new String(String)
; lihat stackoverflow.com/a/390854/8946 .Saat Anda menggunakannya
substring
, itu tidak benar-benar membuat string baru. Itu masih mengacu pada string asli Anda, dengan batasan offset dan ukuran.Jadi, untuk memungkinkan string asli Anda dikumpulkan, Anda perlu membuat string baru (menggunakan
new String
, atau apa yang Anda punya).sumber
Karena string Java terdiri dari array char, start offset dan panjang (dan kode hash yang di-cache). Beberapa operasi String seperti
substring()
membuat objek String baru yang berbagi array char asli dan hanya memiliki bidang offset dan / atau panjang yang berbeda. Ini berfungsi karena array char dari String tidak pernah dimodifikasi begitu telah dibuat.Ini dapat menghemat memori saat banyak substring merujuk ke string dasar yang sama tanpa mereplikasi bagian yang tumpang tindih. Seperti yang Anda perhatikan, dalam beberapa situasi, ini dapat menjaga data yang tidak diperlukan lagi dari pengumpulan sampah.
Cara "benar" untuk memperbaikinya adalah
new String(String)
konstruktor, yaituBTW, solusi terbaik secara keseluruhan adalah untuk menghindari memiliki String yang sangat besar di tempat pertama, dan memproses input dalam potongan yang lebih kecil, beberapa KB sekaligus.
sumber
new String(String)
; lihat stackoverflow.com/a/390854/8946 .Di Jawa string adalah objek yang dapat diubah dan setelah sebuah string dibuat, ia tetap berada di memori sampai dibersihkan oleh pengumpul sampah (dan pembersihan ini bukanlah sesuatu yang dapat Anda terima begitu saja).
Saat Anda memanggil metode substring, Java tidak membuat string yang benar-benar baru, tetapi hanya menyimpan serangkaian karakter di dalam string asli.
Jadi, ketika Anda membuat string baru dengan kode ini:
Anda benar-benar membuat string baru ketika Anda menggabungkan hasilnya dengan string kosong. Itu sebabnya.
sumber
Seperti yang didokumentasikan oleh jwz pada tahun 1997 :
sumber
Singkatnya, jika Anda membuat banyak substring dari sejumlah kecil string besar, maka gunakan
Karena Anda hanya menggunakan ruang untuk menyimpan string besar, tetapi jika Anda mengekstraksi beberapa string kecil, dari kehilangan string besar, maka
Akan membuat daya ingat Anda tetap rendah, karena string besar dapat direklamasi saat tidak lagi diperlukan.
Bahwa Anda menelepon
new String
adalah pengingat yang membantu bahwa Anda benar-benar mendapatkan string baru, daripada referensi ke yang asli.sumber
new String(String)
; lihat stackoverflow.com/a/390854/8946 .Pertama, panggilan
java.lang.String.substring
menciptakan jendela baru pada dokumen asliString
dengan penggunaan offset dan panjang alih-alih menyalin bagian penting dari array yang mendasarinya.Jika kita melihat lebih dekat pada
substring
metode ini kita akan melihat panggilan konstruktor stringString(int, int, char[])
dan meneruskannya keseluruhanchar[]
yang mewakili string . Itu berarti substring akan menempati jumlah memori sebanyak string asli .Ok, tapi mengapa
+ ""
menghasilkan permintaan untuk memori lebih sedikit daripada tanpa itu ??Melakukan
+
aktifstrings
diimplementasikan melaluiStringBuilder.append
pemanggilan metode. Lihatlah implementasi metode ini diAbstractStringBuilder
kelas akan memberitahu kita bahwa itu akhirnya dilakukanarraycopy
dengan bagian yang benar-benar kita butuhkan (itusubstring
).Ada solusi lain ??
sumber
Menambahkan "" ke string terkadang menghemat memori.
Katakanlah saya memiliki string besar yang berisi seluruh buku, satu juta karakter.
Lalu saya membuat 20 string yang berisi bab-bab buku sebagai substring.
Lalu saya membuat 1000 string yang berisi semua paragraf.
Lalu saya membuat 10.000 string yang berisi semua kalimat.
Lalu saya membuat 100.000 string yang berisi semua kata.
Saya masih menggunakan 1.000.000 karakter. Jika Anda menambahkan "" ke setiap bab, paragraf, kalimat, dan kata, Anda menggunakan 5.000.000 karakter.
Tentu saja sama sekali berbeda jika Anda hanya mengekstrak satu kata dari seluruh buku, dan keseluruhan buku itu bisa menjadi sampah yang dikumpulkan tetapi bukan karena satu kata itu memiliki referensi untuk itu.
Dan lagi berbeda jika Anda memiliki string karakter satu juta dan menghapus tab dan spasi di kedua ujungnya, membuat 10 panggilan untuk membuat substring. Cara kerja atau kerja Java menghindari menyalin satu juta karakter setiap kali. Ada kompromi, dan ada baiknya jika Anda tahu apa kompromi itu.
sumber