مقايسه کردن مقادير رشته ای

در این درس از آموزش جاوا، روشهای صحیح مقایسه مقادیر رشتهای بررسی میشود. در جاوا، عملگر ==
فقط آدرس حافظه را مقایسه میکند و برای مقایسه محتوای رشتهها باید از متد equals
استفاده کرد. این متد مقایسهای حساس به حروف بزرگ و کوچک انجام میدهد، درحالیکه equalsIgnoreCase
این حساسیت را نادیده میگیرد. این درس به اهمیت استفاده از این متدها برای جلوگیری از خطاهای منطقی در کدنویسی پرداخته و نحوه پیادهسازی صحیح آنها را همراه با مثالهای عملی توضیح میدهد.
خیلی مواقع ممکن است برای شما پیش بیاید که نیاز پیدا کنید که رشته ها رو با همدیگر مقایسه کنید و شاید متوجه شده باشید استفاده از عملگرهای برابری ساده، مثل عملگرهایی که برای کار با اعداد استفاده میکردیم، برای رشته ها اونطوری که انتظار داریم عمل نمیکند و جواب نمیدهد و برای مقایسه رشته ها احتیاج به چیز دیگری داریم. در این پروژه یعنی CompareStrings، من از قبل دو تا متغیر string اعلان و تعریف کردم. که هر دو آنها یک مقدار دارند و این مقدار برابر با رشته Hello هست.
حالا میخواهم یک کد شرطی به برنامهام اضافه کنم.
در جاوا میتوانید با عبارت if یک کد شرطی ساده بنویسید.
درعبارت if یک شرط boolean داخل یک جفت پرانتز قرار میگیرد.
و من در این شرط میآیم str1 و str2 رو با استفاده از عملگر == مقایسه میکنم.
که به این عملگر، عملگر برابری میگویند و این عملگر برای اعداد، مقادیر بولین و کاراکترها به خوبی کار میکند. برای رشته ها هم ممکن است از نظر ظاهری درست کار کند.
خب؛ در این کد شرطی میگویم که اگر شرط من برقرار بود و عبارت داخل پرانتز true شد، بیا یک رشته رو در خروجی کنسول نمایش بده و این رشته They match! باشد.
بعد در خط کد جدید میآیم یک بند else هم بعد از بند if اضافه میکنم و در کد مربوط به خروجی این قسمت هم میگویم که عبارت They don’t match! در خروجی چاپ بشود.
و از برنامه ام اجرا میگیرم.
ظاهراً به نظر میرسد که همه چیز همانطوری است که انتظارش رو داشتیم. یعنی دو تا رشته با هم برابرند و شرط برقرار بوده و چون شرط مان برقرار بوده، پس عبارت They match! هم در خروجی چاپ شده. ولی دلیل مچ شدن و برابر شدن این دو رشته اون موردی نیست که فکر میکنید.
بیایید یک مثال دیگر برای شما بزنم.
من یک متغیر دیگر با نام str3 ایجاد میکنم و مقدارش رو میگذارم hello با حروف تماماً کوچک.
و بعد یکبار دیگر چند تا کد شرطی برای اجرا آن مینویسم.
میآیم این کد شرطی که این بالا نوشتم رو کپی میکنم و این پایین آنرا پاست میکنم.
و شرطش رو به str1==str3 تغییر میدهم.
و اینبار، با اجرا برنامه میبینیم که باز هم خروجی برنامه مان همان چیزی هست که انتظار داشتیم و عبارت They don’t match! در خروجی چاپ شد.
به وضوح مشخص است که این دو رشته با هم برابر نیستند، چون یکی از آنها با حروف بزرگ هست و یکی از آنها هم با حروف کوچک.
ولی حالا بیایید این رو امتحان کنیم.
من یک متغیر string دیگر با نام part1 ایجاد میکنم و مقدارش رو میگذارم کلمه Hello که اولین حرف آن بزرگ است؛ به علاوه یک کاراکتر space در آخر آن.
بعد میآیم یک متغیر دیگر با نام part2 ایجاد میکنم و مقدارش رو میگذارم World.
این هم حرف اولش رو بزرگ میگذارم.
و بعد میآیم متغیر str4 رو ایجاد میکنم.
و مقدار این متغیر رو با الحاق دو رشته قبلی تعریف میکنم. یعنی part1 + part2.
مسلماً در آینده کاری تان به کرات با اصطلاح concatenate با مفهوم الحاق و چسباندن روبرو خواهید شد. به هرحال؛ حالا من یک رشته با مقدار Hello World باید داشته باشم.
بعد باز هم یک string دیگر ایجاد میکنم با نام str5 و مقدار این رشته رو میگذارم کل عبارتی که داشتم یعنی Hello World.
حالا این دو رشته یعنی str4 و str5 باید با هم مچ و برابر باشند. ولی بیایید ببینیم وقتی این کد شرطی منطقی رو که مشابه آنرا اینجا داشتیم برای این رشته اجرا میکنیم چه اتفاقی میافتد.
من یکبار دیگر این کد شرطی قبلی رو کپی و این پایین آنرا پاست میکنم.
و اینبار متغیرهای str4 و str5 رو باهم مقایسه میکنم و اینبار با اجرا برنامه میبینیم که عبارت They don’t match! در خروجی چاپ میشود. یعنی نتیجه ای بدست اومده که انتظارش را نداشتیم.
خب چه اتفاقی اینجا افتاد؟ چرا اینطوری شد؟
در واقع در مثال اول وقتی اومدیم اولین رشته رو ایجاد کردیم، اون عبارت رشته ای توسط کامپایلر در حافظه ثبت میشود.
بعد زمانی که اومدیم دومین رشته رو ایجاد کردیم، بجای ایجاد یک شیء جدید، کامپایلر میآید به جدول رشته های موجود در حافظه یک نگاهی میکند و میبیند که می تواند یک رشته برابر پیدا کند و بجای ایجاد یک شیء دیگر به راحتی متغیر مرجع دومی رو به شیء اولمان اشاره میدهد. یعنی کامپایلر وقتی میبیند یک رشته برابر با مقداری که میخواهد اختصاص بدهد در حافظه وجود دارد خودش رو راحت میکند و بجای ایجاد یک شیء جدید به همان شیء قبلی که در حافظه هست اشاره میکند.
این روش هیچ مشکلی ایجاد نمیکند. اگر یادتان باشد قبلاً هم گفتم رشته ها در جاوا تغییر ناپذیرند. زمانی که یک شیء string ایجاد میشود، مقدارش دیگر نمیتواند تغییر کند. پس این روش که به راحتی میآید رشته دوم رو به اولی اشاره میدهد، میتواند روش خوبی باشد. پس با وجود همه این چیزها این دو مقدار یکسان هستند و در واقع یکی هستند.
میرویم سراغ مثال بعدی، این دستور شرطی درست جواب نمیدهد چونکه این نوع از مقایسه اصلاً به کوچک و بزرگی حروف حساس نیست. به این فرآیند interning گفته میشود. در واقع کامپایلر میآید یک مقدار دومی رو وارد میکند. بعد در حافظه میگردد دنبال یک مقداری که با این مقدار برابر باشد و بعد یک ارجاعی به اون مقدار وارد میکند.
در این مثال دومی، کامپایلر هیچ مقدار برابری جهت رسیدن به ایده مچ بودن شان در حافظه پیدا نمیکند، پس میآید یک شیء جدید ایجاد میکند و رشته هم تماماً با حروف کوچک هست. در کل در این حالت چون این دو متغیر str3 و str1 دو شیء جداگانه هستند و دو مقدار جداگانه دارند، پس دستور شرطی وارد قسمت else میشود و عبارت They don’t match! رو نمایش میدهد.
خب؛ میرویم سراغ آخرین مثال. در اینجا ما دوتا رشته داریم، part1 و part2. که این دو رشته هر کدام مقادیر خودشان را دارند و دو شیء جداگانه هستند.
در زمان اجرا کامپایلر میخواهد که این دو مقدار رو کنار همدیگر قرار بدهد، ولی چون در حین این فرآیند میبیند که اطلاعات کافی در حافظه وجود ندارد، تصمیم میگیرد str4 رو بعنوان یک شیء جدید دیگر ایجاد کند.
و بعد str5 رو هم داریم که یک شیء کاملاً متفاوت دیگر هست، چرا که کامپایلر نمیداند که این رشته با رشته str4 مچ میشود.
پس زمانی که میآیم مچ بودن این دو مقدار رو تست میکنم وارد قسمت else میشوم و عبارت They don’t match! رو در خروجی به ما نشان میدهد. چونکه این دو تا متغیر دو تا شیء جدا هستند و در حافظه به یک مقدار اشاره ندارند. هر کدام مقدار خودشان را دارند.
برای انجام یک مقایسه دقیق و درست برای رشته ها در جاوا، باید از متدهای equals یا equals IgnoreCase از کلاس string استفاده کنید.
من اول از متد equals استفاده میکنم و این متد رو به عنوان عضوی از شیء str4 صدا میزنم و str5 رو بعنوان پارامتر به آن میدهم و بعد از کدم اجرا میگیرم و اینبار میبیینم که عبارت They match! رو در خروجی به ما نشان میدهد. دقیقاً همان چیزی که انتظارش رو داشتیم.
ولی حالا بیایید ببینیم اگر همه حروف یکی از این مقادیر با حروف بزرگ باشد چه اتفاقی میافتد.
من این کلمه رو تغییر میدهم و WORLD رو با حروف تماماً بزرگ تایپ میکنم.
و یکبار دیگر از کدم اجرا میگیرم و حالا میبینیم که متد equals باعث میشود که عبارت They don’t match! در خروجی چاپ بشود.
ولی بعد میآیم این متدی رو که فراخونی کردم تغیر میدهم. کرسرم رو میگذارم بعد از نام متد یعنی equals و کلیدهای ctrl+space رو فشار میدهم و بجای آن متد equals IgnoreCase رو انتخاب میکنم.
و بعد از کدم اجرا میگیرم و اینبار میبینیم که عبارتThey match! در خروجی چاپ میشود. خب؛ در این درس دیدیم که همیشه برای مقایسه درست و دقیق رشته ها و برای اینکه یک نتیجه درست و مطلوبی بدست بیاوریم باید از متدهای equals یا equals IgnoreCase استفاده کنیم.
هیچوقت از عملگر == استفاده نکنید. در بعضی مواقع ممکن است، این عملگر اون نتیجه ای که میخواهید رو به شما بدهد، ولی نه همیشه. و همیشه این روش در برنامه نویسی روش خوبی نیست. اگر میخواهید نتیجه دقیق و درست و قابل پیش بینی ای در مقایسه رشته ها دریافت کنید، بهتر است بخاطر داشته باشید، که متدهای کلاس های string این امکان رو در اختیار شما قرار میدهند.