ساخت يک رشته با چند مقدار

در این درس از دوره آموزش جامع جاوا، نحوه ساخت یک رشته از چندین مقدار مختلف بررسی میشود. ابتدا به روش سنتی استفاده از عملگر الحاق (+
) پرداخته شده و محدودیتهای آن از جمله مصرف بالای حافظه در عملیات تکراری تشریح میگردد. سپس استفاده از StringBuilder
و متد append
برای مدیریت بهینهتر حافظه و افزایش کارایی معرفی میشود. همچنین، مقایسهای بین String
و StringBuilder
از لحاظ عملکرد و بهینهسازی انجام شده و بهترین روش برای سناریوهای مختلف پیشنهاد میگردد. این درس برای برنامهنویسانی که به بهینهسازی پردازش رشتهها در جاوا نیاز دارند، ضروری است.
در این قسمت از آموزشم میخواهم انواع روش های ادغام رشته ها رو با همدیگر و معایب و مزیت های این روشها رو برای شما توضیح بدهم.
برای این که رشته ها رو با هم ترکیب و ادغام کنیم، میآییم و با استفاده از روش الحاق ساده به راحتی اونها رو کنار همدیگر قرار میدهیم.
من در حال کار روی پروژه ای با نام StringBuilder هستم و همانطور که می بینید از قبل دو تا رشته با مقدار Hello و World ایجاد کردم.
خب؛ حالا میخواهم یک رشته سومی که شامل ترکیبی از این مقادیر به علاوه چند تا کاراکتر دیگر باشد ایجاد کنم.
خب؛ میتوانم اینکار رو انجام بدهم.
پس میآیم رشته سوم خود را ایجاد میکنم و با str1 شروع میکنم و بعد یک کاما اضافه میکنم و یک space، و بعد هم str2 رو به آن اضافه میکنم، و بعد یک علامت تعجب هم در آخر آن اضافه میکنم.
این دستور به خوبی کار میکند و درست هست.
خب؛ میآیم این مقدار رو در خروجی کنسول چاپ میکنم و نشان تان میدهم که قرار دادن رشته ها کنار همدیگر با این روشی که الان انجام دادیم، اون کاری که میخواهیم رو انجام میدهد و به نتیجه دلخواه مان میرسیم، ولی مشکل اینجا است که برای انجام اینکار به این روش، من سه تا متغیر و شیء جداگانه ایجاد کردم. دو تا شیء اولیه که اجزا رشته بودن و شیء سوم هم برای الحاق رشته ها به همدیگر. اگر موردی پیش بیاید که بخواهید با تعداد زیادی رشته کار کنید و اونها رو به هم بچسبانید، این روش میتواند منجر به ایجاد مشکلاتی در مدیریت حافظه بشود.
پس بجای استفاده از این روش پیشنهاد میشود که از یک کلاسی با نام StringBuilder استفاده کنید. این کلاس عضوی از پکیج Java.lang هست، پس برای استفاده از این کلاس نیاز به هیچ ایمپورت خاصی ندارید.
من یک شیء StringBuilder ایجاد میکنم، و نامش رو sb میگذارم و بعنوان نمونه با استفاده از کلمه کلیدی new و بعد متد constructor این کلاس آنرا معرفی میکنم.
منو بازشویی که اینجا برای ما باز میشود نشان میدهد که سه نسخه از این متد constructor برای این کلاس وجود دارد. یکی از این متدها، یک اینتیجر به نام capacity میگیرد. این روشی هست برای تنظیم ظرفیت شیء StringBuilder قبل از استفاده از اون، و زمانی که میدانیم چه مقدار داده داریم که میخواهیم آنها را نگه شان داریم، از این نسخه استفاده میکنیم. در نسخه بعدی از این متد میتوانید اون رو با یک رشته مقداردهی اولیه کنید، یا در نسخه سوم چیزی به نامcharacter sequence داریم.
من میخواهم نسخه string رو استفاده کنم، و میخواهم یک رشته اولیه رو به آن بدهم و رشته Hello رو که قبلاً هم داشتم به آن میدهم.
این عبارت رو تمام میکنم.
حالا میآیم متد append شیء StringBuilder رو برای آن فراخوانی میکنم.
دقت کنید که بعد از تایپ sb.، می بینیم که در لیست پیشنهادی نسخه های زیادی از متد append وجود دارد. که هر کدام از آنها برای یک نوع داده اولیه هستند، یکی برای دنباله یک کاراکتری، یکی برای stringها، و یکی برای یک کلاسی با نام StringBuffer، که اخیراً کمتر استفاده میشود.
من متد append ای که برای string هست رو فراخوانی میکنم، و داخل آن یک کاما و یک space رو وارد میکنم.
و این خط رو تمامش میکنم و بعد با کلیدهای کنترل و d همین خط رو دو بار duplicate میکنم، و بعد دو تا رشته دیگر هم وارد میکنم. برای یکی از آنها کلمه World و بعد هم برای این یکی، یک علامت تعجب.
بعد، نتیجه رو در خروجی نمایش میدهم.
و برای اینکار شیء StringBuilder رو با sb به طور مستقیم به متد println میدهم. به این شکل.
و بعد از کدم اجرا میگیرم، و میبینیم که رشته ها به هم الحاق شدن و دقیقاً همان رشته ای که قبلاً داشتیم مجدد در خروجی چاپ میشود.
ولی ایندفعه، بجای سه شیء فقط یک شیء ایجاد کردم. حالا بیایید تا چیزهای دیگری در مورد شیء StringBuilder به شما بگویم.
هر متدی که شما فراخوانی کنید، مثل append، یک ارجاعی به شیءStringBuilder داده میشود، پس میتوانید فراخوانی هایتان را به صورت زنجیره ای کنار همدیگر قرار بدهید.
مثلاً، در این کد میتوانم بیایم این ارجاع های به شیء sb رو حذف کنم و از شر آنها راحت شوم، و بعد برمیگردم و سمیکالن های خطوط قبلی رو غیر از خط آخر حذف میکنم.
حالا یک تب به ابتدا همه این خطوط اضافه میکنم تا به وضوح مشخص کنم که همه این خطوط مربوط به یک دستور میشوند. برای اضافه کردن تب هم کافی هست از کلید تب روی کیبورد استفاده کنم.
زمانی که برای اولین بار آمدم شیء StringBuilder رو نمونه سازی و معرفی کردم، یک ارجاع به این شیء داده میشود.
و بعد بلافاصله میتوانم متدهای آنرا فراخوانی کنم، و هر بار که متدی را فراخوانی میکنم، از همان ارجاع اولیه استفاده میشود.
یعنی شیء رو ایجاد میکنم و بعد یک مقدار اولیه به آن میدهم، و بعد هم میآیم سه بار متد append رو فراخوانی میکنم.
و دوباره برنامه رو اجرا میکنم و میبینیم که مجدداً نتیجه دقیقاً عین حالت قبلی شد.
ولی با کدی کوتاه تر و مختصرتر. همچنین میتوانید از یک StringBuilder برای جمع آوری داده هایی که کاربر وارد میکند استفاده کنید.
حالا میخواهم از کلاسی به نام Scanner استفاده کنم.
همانطور که در لیست پیشنهادی می بینید این کلاس عضوی از پکیج Java.util هست.
بنابراین وقتی آنرا انتخاب میکنم، یک عبارت ایمپورت به بالا کد من اضافه میشود.
نام شیء Scanner ام رو scanner با s کوچک میگذارم.
پس scanner با S بزرگ یعنی کلاس scanner، و با s کوچک یعنی شیء scanner.
و بعد شیء ام رو با استفاده از کلمه کلیدی new و فراخوانی متد constructor آن نمونه سازی و معرفی اش میکنم.
همانطور که مشخص است متد constructor کلاس scanner تعداد زیادی نسخه های مختلف دارد.
یکی از این نسخه ها چیزی به نام یک input stream میخواهد.
و عبارت System.in دقیقاً همان چیزی هست که اینجا باید وارد کنم.
اگر عبارت System.in رو تایپ کنم، میبینیم که نوع داده آن در لیست نشان داده میشود، درست در سمت راست آن.
پس دارم میگویم که میخواهم داده هایی رو از کنسول بگیرم، دقیقاً مثل زمانی که از عبارت System.out برای نمایش در خروجی کنسول استفاده میکنیم.
حالا میآیم یک دستور رو در خروجی به کاربر نمایش میدهم.
توجه داشته باشید من اینجا از متد print استفاده میکنم، نه println که کرسرم در همان خط باقی بماند.
پس عبارت Enter value رو تایپ میکنم و بعد یک متغیر string به نام input اعلان میکنم و مقدارش رو با صدا زدن متدی با نام Scanner.nextLine تعیین میکنم.
در واقع متد nextLine صبر میکند تا کاربر متنی رو تایپ کند و دکمه اینتر یا Return رو فشار بدهد.
و هر چیزی که کاربر تایپ کند به این متد برگردانده میشود. من میآیم اون مقدار رو در این متغیر ذخیره میکنم.
بعد، نتیجه رو در خروجی نمایش میدهم و عبارتی که کاربر وارد کرده بود رو تکرار میکنم.
از کدم اجرا میگیرم، و میبینیم که عبارت Hello World دوبار در خروجی نمایش داده شده که مربوط به قسمت اول برنامه میشود و بعد دستور Enter value رو میبینیم.
خب؛ اینبار میآیم و در Command prompt ام؛ کلیک میکنم، دقیقاً بعد از علامت دونقطه، عبارت A value رو تایپ میکنم.
بعد اینتر یا Return رو فشار میدهم، و میبینیم که عبارتی رو که وارد کردم به من برمیگرداند و در خروجی نتایج آنرا چاپ میکند.
حالا میخواهم این دو کلاس رو با هم ترکیب کنم، یعنی StringBuilder و Scanner رو.
اول از همه میآیم محتوا StringBuilder رو با این کد پاک میکنم، sb.delete. همانطور که در لیست پیشنهادی مشخص است متد delete دو تا آرگومان میگیرد، که هر دو آنها اینتیجر هست. که یکی از آنها برای کاراکتر اولیه و آن یکی برای کاراکتر نهایی هست.
عدد اولی میتواند صفر باشد. همانطور که قبلاً هم گفتم آرایه ها در جاوا همیشه ایندکس شان از صفر شروع میشود. یعنی ایندکس اولین عنصر در آرایه همیشه صفر هست. بنابراین ایندکس آخرین عنصر میشود تعداد کاراکترها منها یک.
ولی میشود به سادگی تعداد کاراکترها رو در کلاس StringBuilder بدست آورد، و این روش ساده تر و سلیس تر هم است.
برای بدست آوردن این مقدار، باید از عبارت sb.length استفاده کنیم.
Length یک متد از کلاس StringBuilder هست.
پس با این تفاسیر حالا یکبار دیگر از کلاس StringBuilder استفاده میکنم، و از اول شروع میکنم به اضافه کردن.
خب؛ بعد میآیم کدی رو برای یک حلقه تکرار با استفاده از کلمه کلیدی for اضافه میکنم.
کلمه for رو تایپ میکنم، و یک منو pop up میبینیم که برای ما باز میشود، و کاری که میخواهم انجام بدهم این است که میآیم fori رو انتخاب میکنم، تا حلقه تکرار ایجاد بشود.
و وقتی که برای انتخاب fori اینتر یا Return را فشار بدهم، میبینیم که دستور حلقه for کلاسیکی که برای زبان های بر مبنای سی هست برای ما میآورد.
این یک حلقه تکرار هست که برای یک تعداد تکرار مشخص حلقه طراحی شده. که با یک مقدار صفر شروع میشود، که به یک متغیری با نام i اختصاص داده شده، بعد شرط حلقه رو داریم؛ که میگوییم: حلقه تا زمانی ادامه پیدا کند که i برابر با یک مقدار خاصی بشود.
و من این عدد رو سه قرار میدهم.
در قسمت سوم، این عبارت، یعنی i++ رو داریم، که یعنی با هر بار تکرار حلقه یک واحد به متغیر i اضافه بشود.
پس یکبار دیگر به طور کلی میگویم که معنی این دستور چی هست. این دستور دارد میگوید که برای i های از صفر تا کوچکتر از سه یعنی i های برابر با صفر و یک و دو این حلقه تکرار بشود؛ یعنی دستورات داخل آن سه بار اجرا بشوند.
حالا، داخل حلقه for، میآیم دوباره از متغیر input که قبلاً تعریف کردم، عین دفعه قبل استفاده میکنم، یعنی مقدارش رو از دستور Scanner.nextLine بدست میآورم.
بعد در خط جدیدتر، با استفاده از دستور sb.append به StringBuilder اضافه اش میکنم.
و بعد هم مقدار input رو به آن میدهم، ولی یک خط هم به آن اضافه میکنم، که در جاوا برای اینکار از عبارت بک اسلش n داخل یک جفت دابل کوتیشن استفاده میشود.
کلاً هر وقت خواستیم یک خط در جاوا چاپ کنیم، از بک اسلش n استفاده میشود.
پس همانطور که گفتم این کدی که داخل این حلقه هست، در زمان ران گرفتن از حلقه سه بار اجرا میشود.
وقتی کار حلقه تمام شد، میآیم نتیجه رو در خروجی نمایش میدهم.
یکبار دیگر از دستور println استفاده میکنم و شیء StringBuilder رو با تایپ sb به آن میدهم.
بد نیست همینجا این هم بدانید که اگر بخواهید کدتان سلیس تر و واضح تر باشد، میتوانید از دستور sb.toString استفاده کنید، ولی وقتی با شیء builder کار میکنید، متد toString به طور اتوماتیک برایتان فراخوانی میشود، پس نیازی نیست که این کد اضافی رو تایپ کنید.
خب؛ یکبار دیگر از کدم اجرا میگیرم، و وقتی دستور enter value رو در پنجره Command prompt یا نتایج خروجی دیدم میآیم و در کنسول روبرویenter value کلیک میکنم و مقابل آن عبارت a value رو وارد میکنم و اینتر رو میزنم و میبینیم که همان عبارت رو به من برمیگرداند.
این عملیات مربوط میشوند به اجرا قسمت اول کدم یعنی اولین فراخوانی دستورScanner.nextLine. حالا در حلقه for قرار میگیرم، پس تایپ میکنم one، اینتر یا Return رو فشار میدهم، بعد تایپ می کنم two، دوباره اینتر یا Return و اینبار هم تایپ میکنم three؛ و حالا وقتی اینتر یا Return رو فشار میدهم، میبینیم که هر سه مقداری که وارد کردم رو به من نشان میدهد و به من بر می گرداند.
و همانطور که میبینید چون صراحتاً یک خط در آخر هر خروجی اضافه کرده بودم هر مقدار در یک خط چاپ میشود و مقادیر به صورت زیر همی در خروجی نمایش داده میشوند.
خب؛ در این قسمت از آموزش دیدید که چطوری و در چه مواردی میشود از کلاس StringBuilder استفاده کرد تا رشته ها رو در زمان اجرا کنار همدیگر قرار بدهیم، به طوریکه برای اینکار کمترین تعداد اشیاء رو در حافظه ایجاد و تعریف کنیم و دیدید که چطوری میتوانید از کلاس Scanner برای دریافت داده از کاربر در زمان اجرا استفاده کنید.