- Necə qoşulmaq olar?
- İşimdən nümunələr: belə bir faydalı sinif haqqında bilmədən
velosipedqoltuğumu necə yaratdım. - Mənə maraqlı olan digər üsullara baxaq.
- Gəlin ümumiləşdirək.
0. Necə qoşulmaq olar
Mənimlə əl-ələ gəzənlər artıq həm Git, həm də Mavenlə az-çox tanışdırlar, ona görə də bundan sonra bu biliyə arxalanacağam və özümü təkrarlamayacağam. Əvvəlki məqalələrimi qaçıranlar və ya yeni oxumağa başlayanlar üçün burada Maven və Git haqqında materiallar var . Əlbəttə ki, bir quruluş sistemi olmadan (Maven, Gredl) hər şeyi əl ilə də birləşdirə bilərsiniz, lakin bu, indiki vaxtda dəlilikdir və bunu mütləq etmək lazım deyil: hər şeyi necə düzgün edəcəyinizi dərhal öyrənmək daha yaxşıdır. Buna görə də, Maven ilə işləmək üçün əvvəlcə müvafiq asılılığı əlavə edirik:<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${apache.common.version}</version>
</dependency>
Harada ${apache.common.version} bu kitabxananın versiyasıdır. Sonra, bəzi sinifdə idxal etmək üçün idxalı əlavə edin:
import org.apache.commons.lang3.StringUtils;
Və budur, hamısı çantadadır))
1. Real layihədən nümunələr
- sol Pad üsulu
Birinci nümunə, ümumiyyətlə, indi o qədər axmaq görünür ki, həmkarlarımın StringUtils.leftPad haqqında bilməsi və mənə deməsi çox yaxşıdır . Tapşırıq nədən ibarət idi: kod elə qurulmuşdu ki, məlumat düzgün gəlmədiyi təqdirdə onu çevirmək lazım idi. Sətir sahəsinin yalnız rəqəmlərdən ibarət olması gözlənilirdi, yəni. uzunluğu 3 və dəyəri 1-dirsə, giriş “001” olmalıdır. Yəni əvvəlcə bütün boşluqları çıxarmaq lazımdır, sonra isə onu sıfırlarla örtmək lazımdır. Tapşırığın mahiyyətini aydınlaşdırmaq üçün daha çox misal: “12“-dən -> “012” dən “1“ -> “001” və s. Mən nə etdim? Bunu LeftPadExample sinfində təsvir etmişdir . Bütün bunları edəcək bir üsul yazdım:
public static String ownLeftPad(String value) {
String trimmedValue = value.trim();
if(trimmedValue.length() == value.length()) {
return value;
}
StringBuilder newValue = new StringBuilder(trimmedValue);
IntStream.rangeClosed(1, value.length() - trimmedValue.length())
.forEach(it -> newValue.insert(0, "0"));
return newValue.toString();
}
Mən əsas götürdüm ki, biz sadəcə olaraq orijinal və kəsilmiş dəyər arasındakı fərqi əldə edib, qarşısında sıfırlarla doldura bilərik. Bunu etmək üçün eyni əməliyyatı n dəfə etmək üçün IntStream-dən istifadə etdim . Və bu mütləq sınaqdan keçirilməlidir. StringUtils.leftPad metodu haqqında əvvəlcədən bilsəydim nə edə bilərdim :
public static String apacheCommonLeftPad(String value) {
return StringUtils.leftPad(value.trim(), value.length(), "0");
}
Gördüyünüz kimi, kod çox azdır və hər kəs tərəfindən təsdiqlənmiş kitabxana da istifadə olunur. Bu məqsədlə mən LeftPadExampleTest sinfində iki test yaratdım (adətən onlar sinfi sınaqdan keçirməyi planlaşdırdıqda eyni adlı sinif yaradırlar + Eyni paketdə Test, yalnız src/test/java-da). Bu testlər bir üsulu yoxlayır ki, o, dəyəri düzgün çevirir, sonra isə başqa. Əlbəttə ki, daha çox testlər yazılmalıdır, lakin test bizim vəziyyətimizdə əsas mövzu deyil:
package com.github.javarushcommunity.stringutilsdemo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
@DisplayName("Unit-level testing for LeftPadExample")
class LeftPadExampleTest {
@DisplayName("Should transform by using ownLeftPad method as expected")
@Test
public void shouldTransformOwnLeftPadAsExpected() {
//given
String value = "1 ";
String expectedTransformedValue = "0001";
//when
String transformedValue = LeftPadExample.ownLeftPad(value);
//then
Assertions.assertEquals(expectedTransformedValue, transformedValue);
}
@DisplayName("Should transform by using StringUtils method as expected")
@Test
public void shouldTransformStringUtilsLeftPadAsExpected() {
//given
String value = "1 ";
String expectedTransformedValue = "0001";
//when
String transformedValue = LeftPadExample.apacheCommonLeftPad(value);
//then
Assertions.assertEquals(expectedTransformedValue, transformedValue);
}
}
Hələlik testlərlə bağlı bir neçə şərh verə bilərəm. Onlar JUnit 5 istifadə edərək yazılmışdır:
- Test müvafiq annotasiyaya malik olduqda test kimi qəbul ediləcək - @Test.
- Testin işini adda təsvir etmək çətindirsə və ya təsvir uzun və oxunması əlverişsizdirsə, @DisplayName annotasiyasını əlavə edə və onu testlər həyata keçirərkən görünəcək normal təsvir edə bilərsiniz.
- Testləri yazarkən testləri məntiqi hissələrə böldüyüm BDD yanaşmasından istifadə edirəm:
- //verilmiş - testdən əvvəl verilənlərin qurulması bloku;
- //kodun sınaqdan keçirdiyimiz hissəsinin işə salındığı blok nə vaxtdır;
- //sonra zaman blokunun nəticələrinin yoxlanıldığı blokdur.
- stripStart üsulu
Burada mən əvvəlində boşluq və vergül ola bilən sətirlə problemi həll etməli oldum. Transformasiyadan sonra onlar yeni məna kəsb etməməli idilər. Problem ifadəsi həmişəkindən daha aydındır. Bir neçə nümunə anlayışımızı möhkəmləndirəcək: “, , kitablar” -> “kitablar” “,,, kitablar” -> “kitablar” b , kitablar” -> “b , kitablar” SolPad ilə olduğu kimi, mən də əlavə etdim. İki metodu olan StrimStartExample sinfi. Biri - öz həlli ilə:
public static String ownStripStart(String value) {
int index = 0;
List commaSpace = asList(" ", ",");
for (int i = 0; i < value.length(); i++) {
if (commaSpace.contains(String.valueOf(value.charAt(i)))) {
index++;
} else {
break;
}
}
return value.substring(index);
}
Burada fikir boşluq və vergül olmayan indeksi tapmaq idi. Başlanğıcda onlar ümumiyyətlə yox idisə, onda indeks sıfır olacaq. İkincisi - StringUtils vasitəsilə həll yolu ilə :
public static String apacheCommonLeftPad(String value) {
return StringUtils.stripStart(value, StringUtils.SPACE + COMMA);
}
Burada hansı sətirlə işlədiyimiz haqqında birinci arqument məlumatını, ikincidə isə atlanması lazım olan simvollardan ibarət sətri keçirik. StripStartExampleTest sinfini eyni şəkildə yaradırıq :
package com.github.javarushcommunity.stringutilsdemo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("Unit-level testing for StripStartExample")
class StripStartExampleTest {
@DisplayName("Should transform by using stripStart method as expected")
@Test
public void shouldTransformOwnStripStartAsExpected() {
//given
String value = ", , books";
String expectedTransformedValue = "books";
//when
String transformedValue = StripStartExample.ownStripStart(value);
//then
Assertions.assertEquals(expectedTransformedValue, transformedValue);
}
@DisplayName("Should transform by using StringUtils method as expected")
@Test
public void shouldTransformStringUtilsStripStartAsExpected() {
//given
String value = ", , books";
String expectedTransformedValue = "books";
//when
String transformedValue = StripStartExample.apacheCommonLeftPad(value);
//then
Assertions.assertEquals(expectedTransformedValue, transformedValue);
}
}
- isEmpty metodu
Bu üsul, əlbəttə ki, daha sadədir, lakin bu, onu daha az faydalı etmir. O , String.isEmpty() metodunun imkanlarını genişləndirir , bu da null üçün yoxlama əlavə edir. Nə üçün? NullPointerException-dan qaçmaq üçün, yəni null olan dəyişəndə metodları çağırmaqdan qaçınmaq üçün . Buna görə də yazmamaq üçün:
if(value != null && value.isEmpty()) {
//doing something
}
Bunu sadəcə olaraq edə bilərsiniz:
if(StringUtils.isEmpty(value)) {
//doing something
}
Bu metodun üstünlüyü ondan ibarətdir ki, hansı üsuldan istifadə edildiyi dərhal aydın olur.
2. StringUtils sinfinin digər metodlarının təhlili
İndi, mənim fikrimcə, diqqətə layiq olan üsullar haqqında danışaq. Ümumilikdə StringUtils haqqında danışarkən qeyd etmək lazımdır ki, o, String sinfində tapılanlara bənzər null təhlükəsiz metodlar təqdim edir ( isEmpty metodunda olduğu kimi ). Gəlin onlardan keçək:
- müqayisə üsulu
Belə bir üsul String -də mövcuddur və iki sətir müqayisə edərkən onlardan biri null olarsa, NullPointerException atacaq. Kodumuzda çirkin yoxlamaların qarşısını almaq üçün StringUtils.compare(String str1, String str2) metodundan istifadə edə bilərik : o, müqayisə nəticəsində int qaytarır. Bu dəyərlər nə deməkdir? int = 0 eynidirsə (yaxud hər ikisi sıfırdır). int < 0, əgər str1 str2-dən kiçikdirsə. int > 0, əgər str1 str2-dən böyükdürsə. Həmçinin, onların sənədlərinə baxsanız, bu metodun Javadoc proqramı aşağıdakı ssenariləri təqdim edir:
StringUtils.compare(null, null) = 0
StringUtils.compare(null , "a") < 0
StringUtils.compare("a", null) > 0
StringUtils.compare("abc", "abc") = 0
StringUtils.compare("a", "b") < 0
StringUtils.compare("b", "a") > 0
StringUtils.compare("a", "B") > 0
StringUtils.compare("ab", "abc") < 0
- ... üsulları ehtiva edir
Burada kommunal proqram tərtibatçıları bir partlayış yaşadılar. İstədiyiniz üsul var. Onları bir yerə yığmaq qərarına gəldim:
-
ehtiva gözlənilən sətirin başqa bir sətirdə olub olmadığını yoxlayan bir üsuldur. Bu necə faydalıdır? Mətndə müəyyən bir sözün olduğuna əmin olmaq lazımdırsa, bu üsuldan istifadə edə bilərsiniz.
Nümunələr:
StringUtils.contains(null, *) = false StringUtils.contains(*, null) = false StringUtils.contains("", "") = true StringUtils.contains("abc", "") = true StringUtils.contains("abc", "a") = true StringUtils.contains("abc", "z") = false
Yenə də NPE (Null Pointer İstisna) təhlükəsizliyi mövcuddur.
containAny sətirdə mövcud olan simvollardan hər hansı birinin olub-olmadığını yoxlayan bir üsuldur. Həm də faydalı bir şey: bunu tez-tez etməlisiniz. Sənədlərdən nümunələr:
StringUtils.containsAny(null, *) = false StringUtils.containsAny("", *) = false StringUtils.containsAny(*, null) = false StringUtils.containsAny(*, []) = false StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true StringUtils.containsAny("aba", ['z']) = false
-
containIgnoreCase , contain metodunun faydalı uzantısıdır . Həqiqətən, bu üsul olmadan belə bir işi yoxlamaq üçün bir neçə variantdan keçməli olacaqsınız. Beləliklə, yalnız bir üsul ahəngdar şəkildə istifadə ediləcəkdir.
-
containNone - adına əsasən, nəyin yoxlanıldığını artıq başa düşə bilərsiniz. İçəridə heç bir xətt olmamalıdır. Faydalı bir şey, mütləq. Bəzi arzuolunmaz simvollar üçün sürətli axtarış;). Telegram botumuzda ədəbsizləri süzgəcdən keçirəcəyik və bu gülməli üsulları nəzərdən qaçırmayacağıq.
Və misallar, onlarsız harda olardıq:
StringUtils.containsNone(null, *) = true StringUtils.containsNone(*, null) = true StringUtils.containsNone("", *) = true StringUtils.containsNone("ab", '') = true StringUtils.containsNone("abab", 'xyz') = true StringUtils.containsNone("ab1", 'xyz') = true StringUtils.containsNone("abz", 'xyz') = false
Sənədlərdən bir neçə nümunə:
StringUtils.containsIgnoreCase(null, *) = false
StringUtils.containsIgnoreCase(*, null) = false
StringUtils.containsIgnoreCase("", "") = true
StringUtils.containsIgnoreCase("abc", "") = true
StringUtils.containsIgnoreCase("abc", "a") = true
StringUtils.containsIgnoreCase("abc", "z") = false
StringUtils.containsIgnoreCase("abc", "A") = true
StringUtils.containsIgnoreCase("abc", "Z") = false
- defaultString metodu
Əgər sətir boşdursa və siz bəzi standart dəyər təyin etməlisinizsə, əlavə məlumat əlavə etməkdən qaçmağa kömək edən bir sıra üsullar. Hər zövqə uyğun bir çox variant var. Onların arasında ən başlıcası StringUtils.defaultString(son String str, final String defaultStr) - str null olarsa, sadəcə olaraq dəyəri defaultStr- ə keçirəcəyik . Sənədlərdən nümunələr:
StringUtils.defaultString(null, "NULL") = "NULL"
StringUtils.defaultString("", "NULL") = ""
StringUtils.defaultString("bat", "NULL") = "bat"
Məlumatlarla POJO sinfi yaratdığınız zaman istifadə etmək çox rahatdır.
- deleteWhitespace metodu
Bu maraqlı bir üsuldur, baxmayaraq ki, onun tətbiqi üçün bir çox variant yoxdur. Eyni zamanda, belə bir vəziyyət yaranarsa, üsul mütləq çox faydalı olacaqdır. O, sətirdəki bütün boşluqları silir. Bu boşluq haradadırsa, onun izi də qalmayacaq))) Sənədlərdən nümunələr:
StringUtils.deleteWhitespace(null) = null
StringUtils.deleteWhitespace("") = ""
StringUtils.deleteWhitespace("abc") = "abc"
StringUtils.deleteWhitespace(" ab c ") = "abc"
- metodu ilə bitir
Özü üçün danışır. Bu, çox faydalı üsuldur: o, sətirin təklif olunan sətirlə bitib-bitmədiyini yoxlayır. Bu tez-tez lazımdır. Əlbəttə ki, çeki özünüz yaza bilərsiniz, lakin hazır bir üsuldan istifadə etmək daha rahat və daha yaxşıdır. Nümunələr:
StringUtils.endsWith(null, null) = true
StringUtils.endsWith(null, "def") = false
StringUtils.endsWith("abcdef", null) = false
StringUtils.endsWith("abcdef", "def") = true
StringUtils.endsWith("ABCDEF", "def") = false
StringUtils.endsWith("ABCDEF", "cde") = false
StringUtils.endsWith("ABCDEF", "") = true
Gördüyünüz kimi hər şey boş sətirlə bitir))) Məncə bu misal (StringUtils.endsWith("ABCDEF", "") = true) sadəcə bonusdur, çünki bu absurddur) Bir üsul da var ki, halına məhəl qoymur.
- metoduna bərabərdir
İki sətiri müqayisə edən sıfır təhlükəsiz metodun əla nümunəsi. Oraya nə qoysaq, cavab orada olacaq və səhvsiz olacaq. Nümunələr:
StringUtils.equals(null, null) = true
StringUtils.equals(null, "abc") = false
StringUtils.equals("abc", null) = false
StringUtils.equals("abc", "abc") = true
StringUtils.equals("abc", "ABC") = false
Əlbəttə ki, equalsIgnoreCase də var - hər şey eyni şəkildə edilir, yalnız biz işi görməməzlikdən gəlirik. Görək?
StringUtils.equalsIgnoreCase(null, null) = true
StringUtils.equalsIgnoreCase(null, "abc") = false
StringUtils.equalsIgnoreCase("abc", null) = false
StringUtils.equalsIgnoreCase("abc", "abc") = true
StringUtils.equalsIgnoreCase("abc", "ABC") = true
- istənilən üsula bərabərdir
Gəlin davam edək və bərabərlik metodunu genişləndirək . Deyək ki, bir neçə bərabərlik yoxlaması yerinə, birini yerinə yetirmək istəyirik. Bunun üçün bir sıra sətirlərin müqayisə ediləcəyi bir sətir ötürə bilərik, əgər onlardan hər hansı biri təklif edilənə bərabərdirsə, bu, DOĞRU olacaq. Biz onları bir-biri ilə müqayisə etmək üçün simi və sətirlər toplusunu keçirik (kolleksiyadan simlərlə birinci sim). Çətin? Nə demək olduğunu başa düşməyə kömək etmək üçün sənədlərdən nümunələr:
StringUtils.equalsAny(null, (CharSequence[]) null) = false
StringUtils.equalsAny(null, null, null) = true
StringUtils.equalsAny(null, "abc", "def") = false
StringUtils.equalsAny("abc", null, "def") = false
StringUtils.equalsAny("abc", "abc", "def") = true
StringUtils.equalsAny("abc", "ABC", "DEF") = false
EqualsAnyIgnoreCase də var . Və bunun üçün nümunələr:
StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
StringUtils.equalsAnyIgnoreCase(null, null, null) = true
StringUtils.equalsAnyIgnoreCase(null, "abc", "def") = false
StringUtils.equalsAnyIgnoreCase("abc", null, "def") = false
StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
Alt xətt
Nəticədə, StringUtils-in nə olduğunu və onun hansı faydalı metodlara sahib olduğunu bilməklə ayrılırıq. Yaxşı, belə faydalı şeylərin olduğunu başa düşməklə və hər dəfə hazır bir həllin köməyi ilə məsələni bağlamaq mümkün olan yerlərdə qoltuq dəyənəyi ilə hasarlamağa ehtiyac yoxdur. Ümumiyyətlə, biz metodların yalnız bir hissəsini təhlil etdik. İstəyirsinizsə, davam edə bilərəm: daha çoxları var və həqiqətən diqqətə layiqdirlər. Bunun başqa necə təqdim olunacağına dair hər hansı bir fikriniz varsa, yazın - mən həmişə yeni fikirlərə açığam. Metodlar üçün sənədlər çox yaxşı yazılmışdır, nəticələri olan test nümunələri əlavə edilmişdir ki, bu da metodun işini daha yaxşı başa düşməyə kömək edir. Buna görə də, sənədləri oxumaqdan çəkinmirik: bu, yardım proqramının funksionallığı ilə bağlı şübhələrinizi aradan qaldıracaq. Yeni kodlaşdırma təcrübəsi əldə etmək üçün sizə faydalı siniflərin necə hazırlandığını və yazıldığını nəzərdən keçirməyi məsləhət görürəm. Bu, gələcəkdə faydalı olacaq, çünki adətən hər bir layihənin öz hurda sinifləri var və onları yazmaq təcrübəsi faydalı olacaq. Ənənəvi olaraq, Github-dakı hesabıma abunə olmağı təklif edirəm ) Telegram botu ilə layihəmdən xəbəri olmayanlar üçün burada birinci məqaləyə keçid var . Oxuduğunuz üçün hər kəsə təşəkkür edirəm. Aşağıda bəzi faydalı bağlantılar əlavə etdim.faydalı bağlantılar |
---|
GO TO FULL VERSION