JavaRush /Blog Java /Random-MS /substring(..) menghantui saya
IgorBrest
Tahap

substring(..) menghantui saya

Diterbitkan dalam kumpulan
Sebenarnya, atas sebab subjek, saya membenarkan diri saya untuk mendalami String.substring(..). Dan saya mungkin mendapat keputusan yang tidak dijangka, yang saya memutuskan untuk berkongsi dengan anda, Javorashovites yang dikasihi. Kemukakan kepada penghakiman anda, kononnya. Jadi begini. Terdapat pernyataan bahawa rentetan yang dibuat menggunakan kaedah subrentetan(..) menggunakan tatasusunan aksara rentetan asal. Di sini, khususnya, adalah petikan daripada artikel yang baru dibaca "Rujukan Java. String Statik" oleh artikel yang dihormati :
Terdapat nota tentang kaedah subrentetan - rentetan yang dikembalikan menggunakan tatasusunan bait yang sama seperti yang asal
Dan sudah tentu, Javarash Lectures. Berikut adalah petikan dari 22 Dis:
Apabila kita mencipta subrentetan menggunakan kaedah substring, objek String baharu dicipta. Tetapi daripada menyimpan rujukan kepada tatasusunan dengan set aksara baharu, objek ini menyimpan rujukan kepada tatasusunan aksara lama dan pada masa yang sama menyimpan dua pembolehubah yang mana ia menentukan bahagian mana tatasusunan aksara asal kepunyaannya. ... Apabila subrentetan dicipta, tatasusunan aksara tidak disalin ke objek String baharu. Sebaliknya, kedua-dua objek menyimpan rujukan kepada tatasusunan aksara yang sama. Tetapi! Objek kedua menyimpan dua lagi pembolehubah, yang mengandungi yang mana dan berapa banyak aksara tatasusunan ini ditulis kepadanya. ... Oleh itu, jika anda mengambil rentetan sepanjang 10,000 aksara dan membuat 10,000 subrentetan daripada mana-mana panjang daripadanya, maka "subrentetan" ini akan mengambil sedikit memori, kerana tatasusunan aksara tidak diduplikasi. Rentetan yang sepatutnya menggunakan satu tan ruang hanya akan mengambil beberapa bait.
semuanya jelas tertulis, malah dikunyah. Tetapi, kerana saya cuba meningkatkan pengetahuan bahasa Inggeris saya, saya sering beralih kepada dokumentasi rasmi, dan entah bagaimana saya tidak dapat mencari pengesahan fakta ini... Mengaitkan ini dengan kecuaian saya, saya masih melihat kod sumber substring() (terima kasih kepada IDEA membolehkan anda melakukan ini dengan satu klik butang). public String substring(int beginIndex, int endIndex) { if (beginIndex < 0) { throw new StringIndexOutOfBoundsException(beginIndex); } if (endIndex > value.length) { throw new StringIndexOutOfBoundsException(endIndex); } int subLen = endIndex - beginIndex; if (subLen < 0) { throw new StringIndexOutOfBoundsException(subLen); } return ((beginIndex == 0) && (endIndex == value.length)) ? this : new String(value, beginIndex, subLen); } Tertarik, saya pergi lebih jauh: * Allocates a new {@code String} that contains characters from a subarray * of the character array argument. The {@code offset} argument is the * index of the first character of the subarray and the {@code count} * argument specifies the length of the subarray. The contents of the * subarray are copied; subsequent modification of the character array does * not affect the newly created string. public String(char value[], int offset, int count) { if (offset < 0) { throw new StringIndexOutOfBoundsException(offset); } if (count < 0) { throw new StringIndexOutOfBoundsException(count); } // Note: offset or count might be near -1>>>1. if (offset > value.length - count) { throw new StringIndexOutOfBoundsException(offset + count); } this.value = Arrays.copyOfRange(value, offset, offset+count); } di mana Arrays.copyOfRange ialah kaedah asli yang mengembalikan salinan tatasusunan daripada char... Kod yang agak remeh, dan nampaknya jelas kepada saya bahawa baris baharu dengan set aksara baharu dicipta semata-mata. atau saya tidak mengambil kira sesuatu... Jadi, tidak mempercayai sepenuhnya kesimpulan saya, saya memutuskan untuk menguji subrentetan() ini, bergantung pada frasa daripada kuliah:
Oleh itu, jika anda mengambil rentetan sepanjang 10,000 aksara dan membuat 10,000 subrentetan daripada mana-mana panjang daripadanya, maka "subrentetan" ini akan mengambil sedikit memori...
hanya daripada 10_000 kita akan segera membuat 100_000_000, mengapa membuang masa pada perkara-perkara kecil. Saya dengan cepat melemparkan kod berikut: dan inilah yang berlaku: i.e. Setiap kali anda mencipta sub rentetan baharu menggunakan bigString.substring(..), tatasusunan aksara diDUPLICAKAN. Bagaimana lagi kita boleh menjelaskan peningkatan dalam penggunaan ingatan? Selepas ini, saya secara peribadi tidak lagi mempunyai sebarang keraguan mengenai pengendalian kaedah String.substsring(). Bagaimana dengan anda? public class Test { public static void main(String[] args) { System.out.println("Начинаем:"); print(); System.out.println("********************************"); char[]big=new char[100_000_000];//создаем нормальный такой массив int j=0;//и заполняем этот массив всякой ерундой for (int k=0;k list=new ArrayList<>();//здесь будут ссылки на строки, что бы сборщик мусора не удалял //не используемые, по его мнению, строки. System.out.println("************************************"); System.out.println("Теперь будем создавть подстроки с помощью substring(..) и наблюдать," + "что же происходит с памятью"); for (int i = 2; i <10; i++) { //создаем подстроку, используя метод String.substring(..) String sub= bigString.substring(1,bigString.length()-1); //если этот метод не создает fully новый массив символов, а только пользуется //исходным из bigString // то при создании новой строки sub мы не будем наблюдать ощутипый расход памяти list.add(sub);//эти ссылки мы должны где нибудь хранить, иначе сборщик мусора //избавится от неипользуемых объктов String System.out.print(String.format("Создаем %d-ую подстроку, при этом ", i - 1)); print(); } System.out.println("***************************************"); print(); } static void print(){ System.out.println("Памяти используется "+(Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())/1024/1024 + " mb"); } } Начинаем: Памяти используется 0 mb ******************************** создал большую строку bigString на основе массива big. Теперь: Памяти используется 382 mb ************************************ Теперь будем создавть подстроки с помощью substring(..) и наблюдать,что же происходит с памятью Добавляем 1-ую подстроку, при этом Памяти используется 573 mb Добавляем 2-ую подстроку, при этом Памяти используется 763 mb Добавляем 3-ую подстроку, при этом Памяти используется 954 mb Добавляем 4-ую подстроку, при этом Памяти используется 1145 mb Добавляем 5-ую подстроку, при этом Памяти используется 1336 mb Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at java.util.Arrays.copyOfRange(Arrays.java:3658) at java.lang.String. (String.java:201) at java.lang.String.substring(String.java:1956) at com.javarush.test.tests.Test.main(Test.java:42) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134) Process finished with exit code 1
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION