JavaRush /Java Blog /Random-TL /pinagmumultuhan ako ng substring(..).
IgorBrest
Antas

pinagmumultuhan ako ng substring(..).

Nai-publish sa grupo
Sa totoo lang, para sa kadahilanan ng paksa, pinahintulutan ko ang aking sarili na bungkalin ang String.substring(..). At malamang na dumating ako sa hindi inaasahang mga resulta, na nagpasya akong ibahagi sa iyo, mahal na mga Javorashovites. Iharap ito sa iyong paghatol, kumbaga. Kaya eto na. May isang pahayag na ang isang string na nilikha gamit ang substring(..) na pamamaraan ay gumagamit ng character array ng orihinal na string. Narito, sa partikular, ay isang sipi mula sa kamakailang binasang artikulong "Java Reference. Static Strings" ng mga iginagalang na artikulo :
Mayroong tala tungkol sa substring method - ang ibinalik na string ay gumagamit ng parehong byte array gaya ng orihinal
At siyempre, Javarash Lectures. Narito ang mga quote mula Disyembre 22:
Kapag gumawa kami ng substring gamit ang substring method, isang bagong String object ang gagawin. Ngunit sa halip na mag-imbak ng reference sa isang array na may bagong set ng mga character, ang object na ito ay nag-iimbak ng reference sa lumang character array at kasabay nito ay nag-iimbak ng dalawang variable kung saan tinutukoy nito kung aling bahagi ng orihinal na character array ang kabilang dito. ... Kapag ang isang substring ay ginawa, ang character array ay hindi makokopya sa isang bagong String object. Sa halip, ang parehong mga bagay ay nag-iimbak ng isang reference sa parehong array ng character. Ngunit! Ang pangalawang bagay ay nag-iimbak ng dalawa pang variable, na naglalaman kung alin at kung gaano karaming mga character ng array na ito ang nakasulat dito. ... Samakatuwid, kung kukuha ka ng isang string na 10,000 character ang haba at gumawa ng 10,000 substrings ng anumang haba mula dito, ang mga "substrings" na ito ay kukuha ng napakakaunting memorya, dahil ang array ng character ay hindi nadoble. Ang mga string na dapat tumagal ng isang toneladang espasyo ay kukuha lang ng ilang byte.
lahat ay malinaw na nakasulat, kahit ngumunguya. Ngunit, dahil sinusubukan kong pagbutihin ang aking kaalaman sa Ingles, madalas akong bumaling sa opisyal na dokumentasyon, at sa paanuman ay hindi ko mahanap ang kumpirmasyon ng katotohanang ito... Dahil dito ay aking kawalang-ingat, tiningnan ko pa rin ang source code ng substring() (salamat sa IDEA ay nagpapahintulot sa iyo na gawin ito sa isang pag-click ng isang pindutan). 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); } Naintriga, nagpunta pa ako: * 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); } kung saan ang Arrays.copyOfRange ay isang katutubong pamamaraan na nagbabalik ng kopya ng isang array mula sa char... Medyo walang kuwentang code, at tila halata sa akin na ang isang bagong hilera na may bagong hanay ng mga karakter ay simpleng nilikha. o hindi ko isinasaalang-alang ang isang bagay... Kaya, hindi lubos na naniniwala sa aking mga konklusyon, nagpasya akong subukan ang substring() na ito, umaasa sa isang parirala mula sa lecture:
Samakatuwid, kung kukuha ka ng isang string na 10,000 character ang haba at gagawa ka ng 10,000 substring ng anumang haba mula dito, ang mga "substring" na ito ay kukuha ng napakakaunting memorya...
tanging sa halip na 10_000 ay gagawa tayo agad ng 100_000_000, bakit mag-aaksaya ng oras sa mga bagay na walang kabuluhan. Mabilis kong inihagis ang sumusunod na code: at ito ang nangyari: i.e. Sa tuwing gagawa ka ng bagong sub string gamit ang bigString.substring(..), ang array ng character ay DUPLICATED. Paano pa natin maipapaliwanag ang gayong pagtaas sa pagkonsumo ng memorya? Pagkatapos nito, ako mismo ay hindi na nagkaroon ng anumang pagdududa tungkol sa pagpapatakbo ng String.substsring() na pamamaraan. Paano ang tungkol sa iyo? 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
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION