عملیات رایج روی رشته در جاوا — راهنمای کاربردی

مقادیر مبتنی بر رشته و عملیات مرتبط به آنها به صورت روزمره در فرایند کدنویسی مکرر مورد استفاده قرار میگیرند و هر توسعهدهنده جاوا باید بتواند با آنها کار کند. در این مقاله یک راهنمای سریع و کاربردی از عملیات رایج روی رشته در جاوا ارائه میکنیم. به علاوه به بررسی تفاوتهای equals و “==” و همچنین فرقهای بین StringUtils#isBlank و isEmpty# نیز میپردازیم.
تبدیل یک char به رشته
Char نشاندهنده یک کاراکتر در جاوا است، اما در اغلب موارد ما به رشته نیاز داریم.
بنابراین این مقاله را با معرفی روش تبدیل char به رشته آغاز میکنیم:
String toStringWithConcatenation(final char c) { return String.valueOf(c); }
الحاق رشتهها
عملیات رایج دیگر که اغلب مورد نیاز است، الحاق رشتهها با مقادیر دیگر مانند char است:
String appendWithConcatenation(final String prefix, final char c) { return prefix + c; }
ما میتوانیم انواع مقدماتی را با StringBuilder نیز الحاق کنیم:
String appendWithStringBuilder(final String prefix, final char c) { return new StringBuilder(prefix).append(c).toString(); }
دریافت کاراکتر بر اساس اندیس
اگر لازم باشد که دقیقاً یک کاراکتر را از یک رشته استخراج کنیم، میتوانیم از API به این منظور استفاده کنیم:
char getCharacterByIndex(final String text, final int index) { return text.charAt(index); }
از آنجا که یک String از یک []char به عنوان ساختمان داده زیربنایی خود استفاده میکند، اندیس آن از صفر آغاز میشود.
مدیریت مقادیر ASCII
میتوانیم به سادگی بین یک char و بازنمایی عددی آن (ASCII) از طریق تبدیل نوع سوئیچ کنیم:
int asciiValue(final char character) { return (int) character; } char fromAsciiValue(final int value) { Assert.isTrue(value >= 0 && value < 65536, "value is not a valid character"); return (char) value; }
البته از آنجا که یک int در واقع 4 بایت بی علامت و یک char 2 بایت بی علامت است، باید بررسی کنیم تا مطمئن شویم که با مقادیر کاراکتر معتبری کار میکنیم.
حذف همه فاصلههای خالی
گاهی اوقات باید از شر برخی کاراکترها رها شویم که در اغلب موارد شامل فاصلههای خالی میشود. یک روش مناسب استفاده از متد replaceAll به همراه یک «عبارت منظم» (regular expression) است:
String removeWhiteSpace(final String text) { return text.replaceAll("\\s+", ""); }
الحاق کلکسیونها به یک رشته
کاربرد رایج دیگر هنگامی است که یک کلکسیون داریم و میخواهیم یک رشته از روی آن بسازیم:
<T> String fromCollection(final Collection<T> collection) { return collection.stream().map(Objects::toString).collect(Collectors.joining(", ")); }
توجه کنید که Collectors.joining امکان تعیین پیشوند و یا پسوند را فراهم میسازد.
افراز یک رشته
از سوی دیگر گاهی میخواهیم یک رشته را با استفاده از متد split و از طریق یک کاراکتر جداساز به زیرمجموعههایی افراز کنیم:
String[] splitByRegExPipe(final String text) { return text.split("\\|"); }
در این مورد نیز از یک عبارت منظم استفاده میکنیم و این بار به وسیله یک pipe افراز میکنیم. از آنجا که میخواهیم از یک کاراکتر خاص استفاده کنیم باید آن را escape کنیم. امکان دیگر آن است که از کلاس Pattern استفاده کنیم:
String[] splitByPatternPipe(final String text) { return text.split(Pattern.quote("|")); }
پردازش همه کاراکترها به صورت یک استریم
در مورد پردازش تفصیلی میتوانیم یک رشته را به یک IntStream تبدیل کنیم:
IntStream getStream(final String text) { return text.chars(); }
برابری ارجاعی و برابری مقداری
با این که رشتهها شبیه یک «نوع اولیه» (primitive type) به نظر میرسند، اما چنین نیستند. بنابراین باید بین برابری ارجاعی و برابری مقداری تمایز قائل شویم. برابری ارجاعی همواره به معنی برابری مقداری نیز خواهد بود، اما عکس این حالت به طور کلی صادق نیست. بنابراین در ابتدا با عملیات == مقایسه میکنیم و سپس از متد equals استفاده میکنیم:
@Test public void whenUsingEquals_thenWeCheckForTheSameValue() { assertTrue("Values are equal", new String("Test").equals("Test")); } @Test public void whenUsingEqualsSign_thenWeCheckForReferenceEquality() { assertFalse("References are not equal", new String("Test") == "Test"); }
توجه داشته باشید که literal-ها در string pool جاوا وارد شدهاند. از این رو کامپایلر میتواند گاهی اوقات آنها را به همان مرجع بهینه سازی کند:
@Test public void whenTheCompileCanBuildUpAString_thenWeGetTheSameReference() { assertTrue("Literals are concatenated by the compiler", "Test" == "Te"+"st"); }
مقایسه رشتههای خالی با رشتههای تهی
تفاوت ظریفی بین دو متد isBlank و isEmpty وجود دارد. یک رشته زمانی تهی است که null بوده یا طول صفر داشته باشد، در حالی که رشته زمانی خالی است که null یا صرفاً شامل کاراکترهای فاصله باشد:
@Test public void whenUsingIsEmpty_thenWeCheckForNullorLengthZero() { assertTrue("null is empty", isEmpty(null)); assertTrue("nothing is empty", isEmpty("")); assertFalse("whitespace is not empty", isEmpty(" ")); assertFalse("whitespace is not empty", isEmpty("\n")); assertFalse("whitespace is not empty", isEmpty("\t")); assertFalse("text is not empty", isEmpty("Anything!")); } @Test public void whenUsingIsBlank_thenWeCheckForNullorOnlyContainingWhitespace() { assertTrue("null is blank", isBlank(null)); assertTrue("nothing is blank", isBlank("")); assertTrue("whitespace is blank", isBlank("\t\t \t\n\r")); assertFalse("test is not blank", isBlank("Anything!")); }
سخن پایانی
رشتهها یک نوع اساسی در همه انواع اپلیکیشنها محسوب میشوند. در این راهنما با برخی عملیات کلیدی در حالتهای مختلف آشنا شدیم. به علاوه برخی اطلاعات در مورد مرجعهای تفصیلیتر به دست آوردیم. در نهایت باید اشاره کنیم که کد کامل موارد مطرح شده در این مقاله را میتوانید در این ریپوی گیتهاب (+) ملاحظه کنید.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی جاوا (Java)
- گنجینه آموزش های جاوا (Java)
- مجموعه آموزشهای برنامهنویسی
- آموزش مقدماتی جاوا (بخش اول) — از صفر تا صد
- الگوریتم حل ماز (Maze) در جاوا — از صفر تا صد
==