JavaRush /Blog Jawa /Random-JV /Ayo dipecah kelas StringUtils

Ayo dipecah kelas StringUtils

Diterbitake ing grup
Halo kabeh, para pamaca sing daktresnani. Aku nyoba kanggo nulis bab apa tenan kapentingan kula lan apa kuwatir kula ing wayahe. Mulane, dina iki bakal ana sawetara maca cahya sing bakal migunani kanggo sampeyan minangka referensi ing mangsa ngarep: ayo ngomong babagan StringUtils . Ayo mecah kelas StringUtils - 1Kedadeyan sing siji wektu aku ngliwati perpustakaan Apache Commons Lang 3 . Iki minangka perpustakaan kanthi kelas tambahan kanggo nggarap obyek sing beda-beda. Iki minangka kumpulan cara sing migunani kanggo nggarap senar, koleksi, lan liya-liyane. Ing project saiki, ngendi aku kudu bisa ing liyane rinci karo strings nerjemahake logika bisnis 25-taun-lawas (saka COBOL kanggo Jawa), ternyata aku ora duwe kawruh cukup jero saka kelas StringUtils . Dadi aku kudu nggawe kabeh dhewe. Maksudku opo? Kasunyatan sing ora kudu nulis tugas tartamtu nglibatno manipulasi senar dhewe, nanging nggunakake solusi siap-digawe. Apa salahe yen nulis dhewe? Paling ora, iki luwih akeh kode sing wis ditulis ing wektu sing suwe. Ora kurang penting yaiku masalah nguji kode sing ditulis tambahan. Nalika kita nggunakake perpustakaan sing wis mbuktekaken dhewe apik, kita ngarepake sing wis dites lan kita ora perlu kanggo nulis Bunch saka test kasus kanggo nyoba. Iku mung mengkono sing pesawat saka cara kanggo nggarap string ing Jawa ora dadi gedhe. Ana tenan ora akeh cara sing bakal migunani kanggo karya. Kelas iki uga digawe kanggo nyedhiyani mriksa NullPointerException. Outline artikel kita bakal kaya ing ngisor iki:
  1. Carane nyambungake?
  2. Conto saka karyaku: kepiye, tanpa ngerti babagan kelas sing migunani, aku nggawe kruk sepeda .
  3. Ayo goleki cara liyane sing aku nemokake menarik.
  4. Ayo ngringkes.
Kabeh kasus bakal ditambahake menyang repositori sing kapisah ing organisasi Komunitas Javarush ing GitHub. Bakal ana conto lan tes sing kapisah kanggo dheweke.

0. Carane nyambungake

Wong-wong sing mlaku bebarengan karo aku wis luwih utawa kurang kenal karo Git lan Maven, mula aku bakal ngandelake kawruh iki lan ora mbaleni maneh. Kanggo sing ora kejawab artikel sadurunge utawa mung miwiti maca, kene bahan babagan Maven lan Git . Mesthi wae, tanpa sistem mbangun (Maven, Gredl), sampeyan uga bisa nyambungake kabeh kanthi manual, nanging saiki pancen edan lan sampeyan ora perlu nindakake kaya ngono: luwih becik langsung sinau carane nindakake kabeh kanthi bener. Mula, kanggo nggarap Maven, kita kudu nambah ketergantungan sing cocog:
<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-lang3</artifactId>
   <version>${apache.common.version}</version>
</dependency>
Ngendi ${apache.common.version} minangka versi perpustakaan iki. Sabanjure, kanggo ngimpor ing sawetara kelas, tambahake impor:
import org.apache.commons.lang3.StringUtils;
Lan iku, kabeh ana ing tas))

1. Conto saka proyek nyata

  • metode leftPad

Conto pisanan umume katon bodho saiki, amarga kanca-kancaku ngerti babagan StringUtils.leftPad lan ngandhani aku. Apa tugas: kode kasebut dibangun kanthi cara sing perlu kanggo ngowahi data yen ora teka kanthi bener. Sampeyan iki samesthine sing lapangan senar ngirim mung saka nomer, i.e. yen dawane 3 lan regane 1, banjur entri kudu "001". Sing, pisanan sampeyan kudu mbusak kabeh spasi, banjur nutupi karo zeros. Conto liyane kanggo nggawe inti saka tugas cetha: saka "12" -> "012" saka "1" -> "001" Lan ing. Apa sing dak lakoni? Digambarake iki ing kelas LeftPadExample . Aku nulis cara sing bakal nindakake kabeh iki:
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();
}
Minangka basis, Aku njupuk idea sing kita mung bisa njaluk prabédan antarane asli lan Nilai apik lan isi karo nul ing ngarep. Kanggo nindakake iki aku digunakake IntStream kanggo nindakake operasi padha n kaping. Lan iki mesthi kudu dites. Mangkene apa sing bisa ditindakake yen aku ngerti babagan metode StringUtils.leftPad sadurunge :
public static String apacheCommonLeftPad(String value) {
   return StringUtils.leftPad(value.trim(), value.length(), "0");
}
Nalika sampeyan bisa ndeleng, ana akeh kurang kode, lan perpustakaan dikonfirmasi dening everyone uga digunakake. Kanggo maksud iki, aku nggawe loro tes ing kelas LeftPadExampleTest (biasane nalika rencana kanggo nyoba kelas, nggawe kelas kanthi jeneng sing padha + Test ing paket sing padha, mung ing src / test / java). Tes iki mriksa siji cara kanggo mesthekake yen ngowahi nilai kanthi bener, banjur liyane. Mesthine, luwih akeh tes sing kudu ditulis, nanging tes dudu topik utama ing kasus kita:
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);
   }

}
Aku bisa nggawe sawetara komentar babagan tes kanggo saiki. Iki ditulis nggunakake JUnit 5:
  1. Tes bakal dianggep minangka tes yen nduweni anotasi sing cocog - @Test.
  2. Yen angel njlèntrèhaké operasi tes ing jeneng utawa deskripsi dawa lan ora trep kanggo maca, sampeyan bisa nambah anotasi @DisplayName lan nggawe gambaran normal sing bakal katon nalika mbukak tes.
  3. Nalika nulis tes, aku nggunakake pendekatan BDD, ing ngendi aku dibagi tes dadi bagean logis:
    1. // diwenehi - blok persiyapan data sadurunge tes;
    2. // kapan blok ing ngendi bagean kode sing kita tes diluncurake;
    3. // banjur minangka pamblokiran ing ngendi asil pamblokiran nalika dicenthang.
Yen sampeyan mbukak, dheweke bakal ngonfirmasi manawa kabeh bisa digunakake kaya sing dikarepake.

  • metode stripStart

Ing kene aku kudu ngrampungake masalah karo baris sing bisa duwe spasi lan koma ing wiwitan. Sawise owah-owahan, dheweke kudu ora duwe makna anyar. Pernyataan masalah luwih jelas tinimbang sadurunge. Sawetara conto bakal nguatake pemahaman kita: ", , buku" -> "buku" ",,, buku" -> "buku" b , buku" -> "b , buku" Kaya ing kasus leftPad, aku nambahake StrimStartExample kelas , kang wis rong cara. Siji - kanthi solusi dhewe:
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);
}
Ing kene, ide kasebut yaiku kanggo nemokake indeks sing diwiwiti ora ana spasi utawa koma maneh. Yen padha ora ana ing wiwitan, indeks kasebut bakal nol. Lan sing nomer loro - kanthi solusi liwat StringUtils :
public static String apacheCommonLeftPad(String value) {
   return StringUtils.stripStart(value, StringUtils.SPACE + COMMA);
}
Ing kene kita ngliwati informasi argumentasi pisanan babagan senar sing digunakake, lan ing urutan kapindho kita ngliwati senar sing kalebu karakter sing kudu dilewati. Kita nggawe kelas StripStartExampleTest kanthi cara sing padha :
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);
   }
}

  • metode kosong

Cara iki, mesthi, luwih prasaja, nanging ora nggawe kurang migunani. Iku ngluwihi Kapabilitas saka String.isEmpty () cara , kang uga nambah mriksa kanggo null. Kanggo apa? Kanggo ngindhari NullPointerException, yaiku, supaya ora nelpon metode ing variabel sing null . Mulane, supaya ora nulis:
if(value != null && value.isEmpty()) {
   //doing something
}
Sampeyan mung bisa nindakake iki:
if(StringUtils.isEmpty(value)) {
   //doing something
}
Kauntungan saka metode iki yaiku langsung jelas ing endi metode sing digunakake.

2. Analisis metode liyane saka kelas StringUtils

Saiki ayo ngomong babagan metode sing, miturut pendapatku, uga kudu digatekake. Ngomong umum babagan StringUtils , mesthine kudu menehi cara aman null sing padha karo sing ditemokake ing kelas String (kaya cara isEmpty ). Ayo padha liwat:

  • mbandhingake metode

Cara kasebut ana ing String lan bakal mbuwang NullPointerException yen, nalika mbandhingake rong senar, salah sijine null. Kanggo ngindhari pamriksan sing ora becik ing kode kita, kita bisa nggunakake metode StringUtils.compare(String str1, String str2) : ngasilake int minangka asil perbandingan. Apa tegese nilai-nilai kasebut? int = 0 yen padha (utawa loro-lorone null). int <0, yen str1 kurang saka str2. int> 0, yen str1 luwih gedhe tinimbang str2. Uga, yen sampeyan ndeleng dokumentasi, Javadoc saka metode iki nampilake skenario ing ngisor iki:
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

  • ngandhut ... cara

Ing kene para pangembang sarana wis jeblugan. Cara apa wae sing dikarepake ana. Aku mutusake kanggo nggabungake:
  1. ngandhut iku cara sing mriksa apa senar samesthine nang senar liyane. Kepiye carane iki migunani? Sampeyan bisa nggunakake cara iki yen sampeyan kudu nggawe manawa ana tembung tartamtu ing teks.

    Tuladha:

    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

    Maneh, keamanan NPE (Null Pointer Exception).

  2. containsAny minangka cara sing mriksa manawa ana karakter sing ana ing senar kasebut. Uga bab sing migunani: sampeyan kerep kudu nindakake iki.

    Conto saka dokumentasi:

    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

  3. containsIgnoreCase minangka ekstensi migunani kanggo metode ngandhut . Pancen, kanggo mriksa kasus kasebut tanpa metode iki, sampeyan kudu ngliwati sawetara pilihan. Dadi mung siji cara sing bakal digunakake kanthi harmonis.

  4. Sawetara conto saka docs:

    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

  5. containsNone - menehi kritik dening jeneng, sampeyan wis bisa ngerti apa sing dicenthang. Mesthine ora ana garis ing njero. Bab sing migunani, mesthi. Telusuran cepet kanggo sawetara karakter sing ora dikarepake;). Ing bot telegram kita bakal nyaring saru lan ora bakal nglirwakake cara sing lucu iki.

    Lan conto, ing ngendi kita bakal tanpa wong-wong mau:

    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

  • metode defaultString

Serangkaian metode sing mbantu supaya ora nambah informasi tambahan yen senar kasebut null lan sampeyan kudu nyetel sawetara nilai standar. Ana akeh pilihan sing cocog karo saben rasa. Kepala ing antarane yaiku StringUtils.defaultString(string String pungkasan, String defaultStr pungkasan) - yen str null, kita mung bakal ngliwati nilai defaultStr . Conto saka dokumentasi:
StringUtils.defaultString(null, "NULL")  = "NULL"
StringUtils.defaultString("", "NULL")    = ""
StringUtils.defaultString("bat", "NULL") = "bat"
Iku trep banget kanggo nggunakake nalika nggawe kelas POJO karo data.

  • metode deleteWhitespace

Iki minangka cara sing menarik, sanajan ora akeh pilihan kanggo aplikasi kasebut. Ing wektu sing padha, yen kedadeyan kaya ngono, cara kasebut mesthi bakal migunani banget. Iku mbusak kabeh spasi saka senar. Ing endi wae jurang iki, ora bakal ana jejak))) Conto saka docs:
StringUtils.deleteWhitespace(null)         = null
StringUtils.deleteWhitespace("")           = ""
StringUtils.deleteWhitespace("abc")        = "abc"
StringUtils.deleteWhitespace("   ab  c  ") = "abc"

  • ends Kanthi metode

Ngomong dhewe. Iki minangka cara sing migunani banget: mriksa manawa senar kasebut rampung karo senar sing disaranake utawa ora. Iki asring perlu. Mesthi wae, sampeyan bisa nulis cek dhewe, nanging nggunakake metode sing wis siap jelas luwih trep lan luwih apik. Tuladha:
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
Nalika sampeyan bisa ndeleng, kabeh ends karo baris kosong))) Aku sing conto iki (StringUtils.endsWith("ABCDEF", "") = bener) mung bonus, amarga iki khayal) Ana uga cara sing nglirwakake kasus.

  • metode sing padha

Conto gedhe saka cara aman null sing mbandhingaké loro strings. Apa wae sing dilebokake ing kana, jawaban bakal ana, lan ora ana kesalahan. Tuladha:
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
Mesthi, ana uga equalsIgnoreCase - kabeh wis rampung kanthi cara sing padha, mung kita ora nglirwakake kasus kasebut. Ayo ndeleng?
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

  • equalsAny method

Ayo maju lan ngluwihi metode sing padha . Contone, tinimbang sawetara mriksa kesetaraan, kita pengin nindakake siji. Kanggo iki, kita bisa ngliwati senar sing bakal dibandhingake karo senar, yen ana sing padha karo sing diusulake, bakal dadi BENER. Kita ngliwati senar lan koleksi senar kanggo mbandhingake siji liyane (senar pisanan karo senar saka koleksi). angel? Ing ngisor iki conto saka docs kanggo mbantu sampeyan ngerti apa tegese:
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
Ana uga equalsAnyIgnoreCase . Lan conto kanggo:
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

Garis ing ngisor

Akibaté, kita lunga kanthi ngerti apa StringUtils lan cara sing migunani. Inggih, kanthi nyadari manawa ana barang sing migunani lan ora perlu pager saben-saben nganggo kruk ing papan sing bisa nutup masalah kasebut kanthi bantuan solusi sing wis siap. Umumé, kita wis nganalisa mung bagean saka cara. Yen sampeyan pengin, aku bisa nerusake: ana akeh liyane, lan padha pancene pantes manungsa waé. Yen sampeyan duwe gagasan babagan carane bisa diwenehi, tulisen - Aku tansah mbukak kanggo gagasan anyar. Dokumentasi kanggo metode kasebut ditulis kanthi apik, conto tes kanthi asil ditambahake, sing mbantu luwih ngerti operasi metode kasebut. Mulane, kita ora isin maca dokumentasi: bakal ngilangi keraguan sampeyan babagan fungsi sarana kasebut. Kanggo entuk pengalaman coding anyar, aku menehi saran supaya sampeyan ndeleng carane kelas utilitas digawe lan ditulis. Iki bakal migunani ing mangsa ngarep, amarga biasane saben proyek duwe kelas kethokan dhewe, lan pengalaman nulis bakal migunani. Cara tradisional, aku saranake sampeyan langganan akunku ing Github ) Kanggo sing ora ngerti babagan proyekku nganggo bot telegram, iki link menyang artikel pisanan . Matur nuwun kanggo kabeh sing wis maca. Aku wis nambah sawetara pranala migunani ing ngisor iki.
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION