- Jak się połączyć?
- Przykłady z mojej pracy: jak nie wiedząc o tak przydatnych zajęciach, stworzyłem swoją kulę
rowerową. - Przyjrzyjmy się innym metodom, które uznałem za interesujące.
- Podsumujmy.
0. Jak się połączyć
Ci, którzy idą ze mną ramię w ramię, znają już mniej więcej zarówno Gita, jak i Mavena, więc dalej będę polegać na tej wiedzy i nie będę się powtarzać. Dla tych, którzy przegapili moje poprzednie artykuły lub dopiero zaczęli czytać, oto materiały o Mavenie i Gicie . Oczywiście bez systemu kompilacji (Maven, Gredl) można też wszystko podłączyć ręcznie, ale w dzisiejszych czasach jest to szaleństwo i zdecydowanie nie trzeba tego robić w ten sposób: lepiej od razu nauczyć się, jak wszystko zrobić poprawnie. Dlatego, aby pracować z Mavenem, najpierw dodajemy odpowiednią zależność:<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${apache.common.version}</version>
</dependency>
Gdzie ${apache.common.version} to wersja tej biblioteki. Następnie, aby zaimportować w jakiejś klasie, dodaj import:
import org.apache.commons.lang3.StringUtils;
I to wszystko, wszystko jest w torbie))
1. Przykłady z prawdziwego projektu
- metoda leftPad
Pierwszy przykład ogólnie wydaje się teraz tak głupi, że bardzo dobrze, że moi koledzy wiedzieli o StringUtils.leftPad i mi powiedzieli. Jakie było zadanie: kod został zbudowany w taki sposób, że konieczne było przekształcenie danych, jeśli nie dotarły całkiem poprawnie. Oczekiwano, że pole tekstowe powinno składać się wyłącznie z liczb, tj. jeśli jego długość wynosi 3, a jego wartość wynosi 1, wówczas wpis powinien mieć wartość „001”. Oznacza to, że najpierw musisz usunąć wszystkie spacje, a następnie pokryć je zerami. Więcej przykładów, aby wyjaśnić istotę zadania: od „12” -> „012” od „1” -> „001” I tak dalej. Co ja zrobiłem? Opisano to w klasie LeftPadExample . Napisałem metodę, która zrobi to wszystko:
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();
}
Jako podstawę przyjąłem pomysł, że możemy po prostu uzyskać różnicę między wartością oryginalną a wartością przyciętą i wypełnić ją zerami z przodu. Aby to zrobić, użyłem IntStream do wykonania tej samej operacji n razy. I to zdecydowanie trzeba przetestować. Oto, co mógłbym zrobić, gdybym wiedział wcześniej o metodzie StringUtils.leftPad :
public static String apacheCommonLeftPad(String value) {
return StringUtils.leftPad(value.trim(), value.length(), "0");
}
Jak widać, kodu jest znacznie mniej, a korzysta się także z biblioteki potwierdzonej przez wszystkich. W tym celu stworzyłem dwa testy w klasie LeftPadExampleTest (zwykle gdy planują przetestować klasę, tworzą klasę o tej samej nazwie + Test w tym samym pakiecie, tylko w src/test/java). Testy te sprawdzają jedną metodę, aby upewnić się, że poprawnie przekształca wartość, a następnie inną. Oczywiście trzeba by napisać znacznie więcej testów, ale w naszym przypadku testowanie nie jest głównym tematem:
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);
}
}
Na razie mogę podzielić się kilkoma uwagami na temat testów. Są one napisane przy użyciu JUnit 5:
- Test będzie traktowany jako test, jeśli będzie opatrzony odpowiednią adnotacją - @Test.
- Jeśli opisanie działania testu w nazwie jest trudne lub opis jest długi i niewygodny w czytaniu, możesz dodać adnotację @DisplayName i uczynić go normalnym opisem, który będzie widoczny podczas uruchamiania testów.
- Pisząc testy stosuję podejście BDD, w którym testy dzielę na logiczne części:
- //podano - blok ustawień danych przed testem;
- //kiedy jest blok, w którym uruchamiana jest część kodu, którą testujemy;
- //then to blok, w którym sprawdzane są wyniki bloku kiedy.
- metoda stripStart
Tutaj musiałem rozwiązać problem z linią, która na początku mogła zawierać spacje i przecinki. Po transformacji nie powinny mieć nowego znaczenia. Opis problemu jest wyraźniejszy niż kiedykolwiek. Kilka przykładów wzmocni nasze zrozumienie: „, , książki” -> „książki” „,,, książki” -> „książki” b , książki” -> „b , książki” Podobnie jak w przypadku leftPad, dodałem Klasa StrimStartExample , w której znajdują się dwie metody. Jeden - z własnym rozwiązaniem:
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);
}
Tutaj pomysł polegał na znalezieniu indeksu, od którego nie ma już spacji ani przecinków. Jeśli na początku w ogóle ich nie było, wówczas indeks będzie wynosił zero. A drugi - z rozwiązaniem poprzez StringUtils :
public static String apacheCommonLeftPad(String value) {
return StringUtils.stripStart(value, StringUtils.SPACE + COMMA);
}
Tutaj w pierwszym argumencie przekazujemy informację o tym, z jakim ciągiem pracujemy, a w drugim podajemy ciąg składający się ze znaków, które należy pominąć. Klasę StripStartExampleTest tworzymy w ten sam sposób :
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);
}
}
- metoda isEmpty
Ta metoda jest oczywiście znacznie prostsza, ale to nie czyni jej mniej użyteczną. Rozszerza możliwości metody String.isEmpty() , która dodaje również sprawdzanie wartości null. Po co? Aby uniknąć wyjątku NullPointerException, to znaczy uniknąć wywoływania metod na zmiennej, która ma wartość null . Żeby więc nie pisać:
if(value != null && value.isEmpty()) {
//doing something
}
Możesz po prostu to zrobić:
if(StringUtils.isEmpty(value)) {
//doing something
}
Zaletą tej metody jest to, że od razu wiadomo, która metoda jest stosowana.
2. Analiza pozostałych metod klasy StringUtils
Porozmawiajmy teraz o tych metodach, które moim zdaniem również zasługują na uwagę. Mówiąc ogólnie o StringUtils warto powiedzieć, że udostępnia on bezpieczne metody null, analogiczne do tych, które znajdziemy w klasie String (tak jak ma to miejsce w przypadku metody isEmpty ). Przejrzyjmy je:
- porównaj metodę
Taka metoda istnieje w String i zgłosi wyjątek NullPointerException, jeśli podczas porównywania dwóch ciągów jeden z nich ma wartość null. Aby uniknąć brzydkich kontroli w naszym kodzie, możemy użyć metody StringUtils.compare(String str1, String str2) : zwraca ona wartość int jako wynik porównania. Co oznaczają te wartości? int = 0, jeśli są takie same (lub oba mają wartość null). int < 0, jeśli str1 jest mniejszy niż str2. int > 0, jeśli str1 jest większy niż str2. Ponadto, jeśli spojrzysz na ich dokumentację, Javadoc tej metody przedstawia następujące scenariusze:
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
- zawiera... metody
Tutaj twórcy narzędzi świetnie się bawili. Dostępna jest jakakolwiek metoda, którą chcesz. Postanowiłem je połączyć:
-
zawiera to metoda sprawdzająca, czy oczekiwany ciąg znaków znajduje się wewnątrz innego ciągu. Jak to jest przydatne? Możesz skorzystać z tej metody, jeśli chcesz się upewnić, że w tekście znajduje się określone słowo.
Przykłady:
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
Ponownie obecne są zabezpieczenia NPE (wyjątek wskaźnika zerowego).
zawieraAny to metoda sprawdzająca, czy występuje którykolwiek ze znaków występujących w ciągu. Również przydatna rzecz: często musisz to robić. Przykłady z dokumentacji:
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
-
zawieraIgnoreCase jest użytecznym rozszerzeniem metody zawiera . Rzeczywiście, aby sprawdzić taki przypadek bez tej metody, będziesz musiał przejść przez kilka opcji. I tak tylko jedna metoda będzie stosowana harmonijnie.
-
zawieraNone - sądząc po nazwie, można już zrozumieć, co jest sprawdzane. Wewnątrz nie powinno być żadnych linii. Zdecydowanie przydatna rzecz. Szybkie wyszukiwanie niechcianych postaci ;). W naszym bocie telegramowym będziemy filtrować wulgaryzmy i nie będziemy ignorować tych zabawnych metod.
I przykłady, gdzie bylibyśmy bez nich:
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
Kilka przykładów z dokumentów:
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
- metoda domyślnaString
Seria metod, które pomagają uniknąć dodawania dodatkowych informacji, jeśli ciąg znaków ma wartość null i trzeba ustawić wartość domyślną. Istnieje wiele opcji, które zaspokoją każdy gust. Najważniejszym z nich jest StringUtils.defaultString(final String str, final String defaultStr) - w przypadku, gdy str ma wartość null, po prostu przekażemy wartość defaultStr . Przykłady z dokumentacji:
StringUtils.defaultString(null, "NULL") = "NULL"
StringUtils.defaultString("", "NULL") = ""
StringUtils.defaultString("bat", "NULL") = "bat"
Jest bardzo wygodny w użyciu, gdy tworzysz klasę POJO z danymi.
- metoda usuwania białych znaków
Jest to ciekawa metoda, choć możliwości jej zastosowania nie jest zbyt wiele. Jednocześnie, jeśli pojawi się taki przypadek, metoda z pewnością będzie bardzo przydatna. Usuwa wszystkie spacje z ciągu. Gdziekolwiek jest ta luka, nie będzie po niej śladu))) Przykłady z dokumentów:
StringUtils.deleteWhitespace(null) = null
StringUtils.deleteWhitespace("") = ""
StringUtils.deleteWhitespace("abc") = "abc"
StringUtils.deleteWhitespace(" ab c ") = "abc"
- kończy się metodą
Mówi samo za siebie. Jest to bardzo przydatna metoda: sprawdza, czy ciąg kończy się sugerowanym ciągiem, czy nie. Jest to często konieczne. Można oczywiście wypisać czek samodzielnie, jednak skorzystanie z gotowego sposobu jest zdecydowanie wygodniejsze i lepsze. Przykłady:
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
Jak widać wszystko kończy się pustą linijką))) Myślę, że ten przykład (StringUtils.endsWith("ABCDEF", "") = true) to tylko bonus, bo to absurd) Istnieje również metoda, która ignoruje wielkość liter.
- metoda równa się
Świetny przykład bezpiecznej metody o wartości null, która porównuje dwa ciągi. Cokolwiek tam umieścimy, odpowiedź będzie tam i będzie bez błędów. Przykłady:
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
Oczywiście jest też równościIgnoreCase – wszystko odbywa się dokładnie w ten sam sposób, tyle że ignorujemy wielkość liter. Zobaczmy?
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
- metoda równaAny
Przejdźmy dalej i rozszerzmy metodę równości . Załóżmy, że zamiast kilku kontroli równości chcemy przeprowadzić jedną. W tym celu możemy przekazać ciąg znaków, z którym zostanie porównany zbiór ciągów; jeśli któryś z nich będzie równy zaproponowanemu, będzie to PRAWDA. Przekazujemy ciąg znaków i kolekcję ciągów, aby je ze sobą porównać (pierwszy ciąg z ciągami z kolekcji). Trudny? Oto przykłady z dokumentów, które pomogą Ci zrozumieć, co to oznacza:
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
Istnieje również RównaAnyIgnoreCase . I przykłady na to:
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
Konkluzja
Dzięki temu wychodzimy z wiedzą czym jest StringUtils i jakie ma przydatne metody. No cóż, ze świadomością, że są takie przydatne rzeczy i nie ma potrzeby każdorazowego płoszenia się kulami w miejscach, w których dałoby się zamknąć sprawę za pomocą gotowego rozwiązania. Ogólnie rzecz biorąc, przeanalizowaliśmy tylko część metod. Jeśli chcesz, mogę kontynuować: jest ich znacznie więcej i naprawdę zasługują na uwagę. Jeśli masz pomysł jak inaczej można by to przedstawić, napisz – zawsze jestem otwarty na nowe pomysły. Dokumentacja metod jest napisana bardzo dobrze, dodano przykłady testów z wynikami, co pozwala lepiej zrozumieć działanie metody. Dlatego nie boimy się zapoznać z dokumentacją: rozwieje ona Twoje wątpliwości co do funkcjonalności narzędzia. Aby zdobyć nowe doświadczenie w kodowaniu, radzę przyjrzeć się sposobowi tworzenia i pisania klas narzędziowych. Przyda się to w przyszłości, ponieważ zazwyczaj każdy projekt ma swoje własne klasy złomu, a doświadczenie w ich pisaniu się przyda. Tradycyjnie proponuję subskrybować moje konto na Githubie ) Dla tych, którzy nie wiedzą o moim projekcie z botem telegramowym, poniżej link do pierwszego artykułu . Dziękuję wszystkim za przeczytanie. Poniżej dodałem kilka przydatnych linków.Przydatne linki |
---|
GO TO FULL VERSION