Клас StringBuffer
Ако програмистите могат да работят изключително с низове само за четене, ще трябва да се създаде нов String обект за всеки междинен резултат от последователни операции с низове. Например, нека помислим как компилаторът ще оцени следния израз:
публичен статичен низ guillemete (кавичка на низ)
Ако компилаторът беше ограничен до изрази от тип String, той би действал така:
Всяко извикване на valueOf и concat създава нов String обект; следователно в резултат на такава операция ще се появят четири String обекта, от които само един ще бъде използван по-късно. Що се отнася до останалото, създаването им, присвояването на първоначални стойности и изтриването им ще включва допълнителни разходи.
Разбира се, компилаторът е много по-ефективен. Обектите StringBuffer се използват за изграждане на междинни низове, а крайните String обекти се създават само когато е необходимо. Обектите на StringBuffer могат да се променят, така че не са необходими нови обекти за съхраняване на междинни резултати. Използвайки StringBuffer, горният израз може да бъде представен по следния начин:
цитиран = нов StringBuffer().append('"').
Тази опция създава само един обект StringBuffer, който съхранява низа, добавя нови фрагменти към него и използва метода toString, за да конвертира резултатите от своята работа в String обект.
Можете да използвате класа StringBuffer, за да конструирате и модифицирате низ.
съдържа следните конструктори:
Конструира нов StringBuffer обект, чиято начална стойност е "". publicStringBuffer(String str)
Конструира нов StringBuffer обект, оригиналната стойносткоето съвпада с str.
наподобява класа String по много начини и много от методите, които съдържа, имат същите имена и договори като методите String. StringBuffer обаче не е разширение на String и обратното. И двата класа са независими разширения на класа Object.
8.8.1. Модификация на буфера
Има няколко начина за промяна на съдържанието на буфера на StringBuffer обект, включително добавяне на нови знаци в края или вмъкването им в средата. Най-простият от тези методи се нарича setCharAt и се използва за замяна на знак на конкретна позиция. Има и метод за замяна, който прави същото като
String.replace обаче работи върху обект StringBuffer. Методът replace не трябва да създава нов обект, за да задържи резултата, така че множество последователни извиквания за replace могат да бъдат направени с един и същ буфер:
публична статична празнота
replace(StringBuffer str, char from, char to)
за (int i = 0; i > buf.length())
хвърляне на нов IndexOutOfBoundsException();
int остатък = buf.length() - (pos + cnt);
char[] chrs = нов char[остатъчно]; buf.getChars(pos + cnt, buf.Length(), chrs, 0); buf.setLength(поз);
На първо място, трябва да се уверите, че стойностите на индексите на масива не излизат извън диапазона. Можете да се справите с изключението по-късно, но незабавното му отчитане ви дава повече контрол върху ситуацията. След това изчисляваме колко елемента има след частта от масива, която трябва да бъде премахната; ако няма такива елементи, съкратете буфера и се върнете. В противен случай, преди да се върнете от метода, е необходимо да изберете тези символи с помощта на метода getChars, след това да изрежете буфера и да добавите предварително разпределения остатък към него.
8.8.3. Работи сбуферен капацитет
Буферът на обекта StringBuffer има определен капацитет - това е максималната дължина на низа, който може да се побере в него, преди да трябва да
отделете допълнително пространство. Буферът може да нараства автоматично при добавяне на нови символи, но за ефективност е желателно да зададете размера му веднъж.
Първоначалният размер на буфера на обект StringBuffer може да бъде зададен с помощта на конструктора,
получаване само на един параметър от тип int:
publicStringBuffer(int капацитет)
Конструира нов StringBuffer обект с даден първоначален капацитет и начална стойност "".
public synchronized voidensureCapacity(int minimum)
Позволява ви да се уверите, че буферът има капацитет поне от определения минимум. public intcapacity()
Връща текущия капацитет на буфера.
Използвайки тези методи, можете да избегнете умножаването на буфера. Следното е нова версия на метода sqrtInt, който предоставя не повече от едно разпределение на ново буферно пространство:
Низ sqrtIntFaster(int i)
StringBuffer buf = нов StringBuffer(50); buf.append("sqrt(").append(i).append(')'); buf.append(" = ").append(Math.sqrt(i)); връщане buf.toString();
Единствената промяна е, че този път се използва конструктор, който създава обект StringBuffer, достатъчно голям, за да побере резултатния низ. Стойността от 50 е малко по-висока от изискваната максимална стойност; следователно буферът никога няма да има нужда да се преоразмерява.
Напишете метод за преобразуване на низове с десетични числа, който поставя запетая след всяка трета цифра вдясно. Например, за оригиналния низ „1542729" методът трябвавръща низа "1,542,729".
Модифицирайте метода от предишното упражнение, така че когато го извикате, можете да укажете знака за разделител и броя на цифрите между разделителите.
Как можеш да си на две места едновременно, когато всъщност си никъде?Firesign Theatre
Повечето програмисти са свикнали да пишат програми, които се изпълняват стъпка по стъпка, в определена последователност. Илюстрацията по-долу показва как банковото салдо се извлича, сумата в сметката се увеличава и се записва обратно в записа на сметката:
Подобни действия се извършват както от живи банкови служители, така и от компютърни програми. Такава последователност от действия, извършвани едно по едно, се наричапоток (th read). В повечето езици програмистите трябва да се справят седнонишковиямодел на програмиране.
В реалните банки обаче такива операции се извършват едновременно. Няколко служители могат независимо да актуализират състоянието на банковите сметки:
Аналогът на тази ситуация в компютъра се наричамногопоточност. Една нишка (като банков служител) може да работи независимо от други нишки. И точно както двама банкови касиери могат да споделят едни и същи шкафове, нишките също споделят обекти.
Споделянето е едновременно една от най-полезните функции на многопоточността и един от най-големите проблеми. Когато използвате схемата fetch-modify-write по-горе, съществува потенциална опасност, ако две нишки работят върху един и същ обект едновременно, да възникне припокриване, което да доведе до унищожаване на обекта. Нека даНека си представим, че в нашия пример с банка някой иска да депозира средства по сметка.
Почти едновременно вторият клиент нарежда на друг банков служител да внесе пари в същата сметка. И двамата служители отиват в архива, за да намерят информация за сметката (имаше моменти, когато банките използваха хартиени шкафове!) и получават едни и същи данни. След това се връщат на масите си, депозират необходимата сума в сметката и се връщат в архива, за да запишат резултатите си, получени независимо един от друг. В този случай само последната от записаните транзакции ще бъде отразена в салдото по сметката; първата транзакция просто ще бъде загубена.
В реалните банки проблемът беше решен просто: служителят остави бележка в папката
"Зает; моля, изчакайте завършването". Почти същото се случва на компютър.
най-много: концепциятазаключване (заключване)се свързва с обекта, чрез който е възможно да се определи дали
обектът се използва или не.
Много задачи за програмиране в реалния свят се решават най-добре с помощта на множество нишки. Например, интерактивни програми, предназначени да показват данни графично, често позволяват на потребителя да променя настройките на дисплея в реално време. Оптималното динамично поведение на интерактивните програми се постига чрез използването на нишки. В еднонишковите системи илюзията за работа с множество нишки обикновено се постига чрез използването на прекъсвания илипрограмни заявки (polling). Програмните заявки се използват за обединяване на частите на приложение, които контролират показването на информация и въвеждането на данни. Програмата за показване трябва да бъде особено внимателно написана - заявките от нея трябва да идват достатъчно често, за да отговарят на въвеждане от потребителя в рамките на удари.секунди. Тази програма трябва или да гарантира, че графичният изход отнема възможно най-малко време, или да прекъсне собствената си работа, за да изпълни заявки. Това смесване на два различни аспекта на една програма води до сложен и понякога нежизнеспособен код.
Тези проблеми се решават най-лесно в многонишкова система. Едната нишка актуализира изображението въз основа на текущите данни, а другата обработва въведеното от потребителя. Ако входът се окаже сложен (например, потребителят попълва екранна форма), първият поток (изход на данни) може да работи независимо, докато не бъде получена нова информация. В програмен модел на заявка трябва или да поставите на пауза актуализацията на изображението, за да изчакате нетривиалното въвеждане да завърши, или да извършите сложна синхронизация, така че изображението да може да се актуализира, докато потребителят попълва формуляра. Моделът с разделен вход-дисплей може да се поддържа директно в многопоточна система, вместо да бъде пренастроен за следващата задача.
Източник: Arnold C., Gosling D. - Езикът за програмиране Java (1997)