- Làm thế nào để kết nối?
- Ví dụ từ công việc của tôi: làm thế nào mà không biết về một lớp học hữu ích như vậy, tôi đã tạo ra chiếc nạng
xe đạpcủa mình . - Hãy xem xét các phương pháp khác mà tôi thấy thú vị.
- Hãy tóm tắt.
0. Cách kết nối
Những người đi cùng tôi ít nhiều đều đã quen thuộc với cả Git và Maven, vì vậy tôi sẽ dựa vào kiến thức này hơn nữa và không lặp lại nữa. Đối với những người đã bỏ lỡ các bài viết trước của tôi hoặc mới bắt đầu đọc, đây là tài liệu về Maven và Git . Tất nhiên, nếu không có hệ thống xây dựng (Maven, Gredl), bạn cũng có thể kết nối mọi thứ theo cách thủ công, nhưng ngày nay điều này thật điên rồ và bạn chắc chắn không cần phải làm như vậy: tốt hơn là bạn nên học ngay cách làm mọi thứ một cách chính xác. Do đó, để làm việc với Maven, trước tiên chúng ta thêm phần phụ thuộc thích hợp:<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${apache.common.version}</version>
</dependency>
Trong đó ${apache.common.version} là phiên bản của thư viện này. Tiếp theo, để nhập vào một số lớp, hãy thêm nhập:
import org.apache.commons.lang3.StringUtils;
Và thế là xong, tất cả đều có trong túi))
1. Ví dụ từ một dự án thực tế
- phương pháp leftPad
Ví dụ đầu tiên nhìn chung có vẻ ngu ngốc đến nỗi thật tốt khi các đồng nghiệp của tôi biết về StringUtils.leftPad và nói với tôi. Nhiệm vụ là gì: mã được xây dựng theo cách cần thiết để chuyển đổi dữ liệu nếu nó không đến nơi chính xác. Người ta mong đợi rằng trường chuỗi chỉ nên bao gồm các số, tức là nếu độ dài của nó là 3 và giá trị của nó là 1 thì mục nhập phải là “001”. Nghĩa là, trước tiên bạn cần xóa tất cả các khoảng trắng, sau đó che nó bằng các số 0. Thêm ví dụ để làm rõ bản chất của nhiệm vụ: từ “12“ -> “012” từ “1“ -> “001”, v.v. Tôi đã làm gì? Đã mô tả điều này trong lớp LeftPadExample . Tôi đã viết một phương pháp sẽ thực hiện tất cả điều này:
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();
}
Về cơ bản, tôi lấy ý tưởng rằng chúng ta có thể chỉ cần lấy chênh lệch giữa giá trị ban đầu và giá trị đã cắt bớt và điền vào đó bằng số 0 ở phía trước. Để làm điều này, tôi đã sử dụng IntStream để thực hiện thao tác tương tự n lần. Và điều này chắc chắn cần phải được kiểm tra. Đây là những gì tôi có thể làm nếu tôi biết trước về phương thức StringUtils.leftPad :
public static String apacheCommonLeftPad(String value) {
return StringUtils.leftPad(value.trim(), value.length(), "0");
}
Như bạn có thể thấy, có ít mã hơn nhiều và một thư viện được mọi người xác nhận cũng được sử dụng. Với mục đích này, tôi đã tạo hai bài kiểm tra trong lớp LeftPadExampleTest (thông thường khi họ định kiểm tra một lớp, họ tạo một lớp có cùng tên + Kiểm tra trong cùng một gói, chỉ trong src/test/java). Các thử nghiệm này kiểm tra một phương thức để đảm bảo rằng nó biến đổi giá trị một cách chính xác, sau đó là một phương thức khác. Tất nhiên, sẽ cần phải viết nhiều bài kiểm tra hơn, nhưng kiểm tra không phải là chủ đề chính trong trường hợp của chúng tôi:
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);
}
}
Bây giờ tôi có thể đưa ra một vài nhận xét về các bài kiểm tra. Chúng được viết bằng JUnit 5:
- Một bài kiểm tra sẽ được coi là một bài kiểm tra nếu nó có chú thích thích hợp - @Test.
- Nếu khó mô tả hoạt động của thử nghiệm bằng tên hoặc mô tả dài và khó đọc, bạn có thể thêm chú thích @DisplayName và đặt chú thích đó thành mô tả bình thường sẽ hiển thị khi chạy thử nghiệm.
- Khi viết bài kiểm tra, tôi sử dụng phương pháp BDD, trong đó tôi chia bài kiểm tra thành các phần logic:
- // đã cho - khối thiết lập dữ liệu trước khi kiểm tra;
- // khi nào khối mà phần mã mà chúng ta đang kiểm tra được khởi chạy;
- // then là khối trong đó kết quả của khối when được kiểm tra.
- phương thức dải Bắt đầu
Ở đây tôi cần giải quyết vấn đề với một dòng có thể có dấu cách và dấu phẩy ở đầu. Sau khi chuyển đổi, lẽ ra chúng không còn có ý nghĩa mới nữa. Tuyên bố vấn đề rõ ràng hơn bao giờ hết. Một vài ví dụ sẽ củng cố sự hiểu biết của chúng ta: “, , books” -> “books” “,,, books” -> “books” b , books” -> “b , books” Như trong trường hợp với leftPad, tôi đã thêm Lớp StrimStartExample , trong đó có hai phương thức. Một - với giải pháp riêng của nó:
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);
}
Ở đây, ý tưởng là tìm chỉ mục bắt đầu từ đó không còn dấu cách hoặc dấu phẩy. Nếu chúng hoàn toàn không có ở đó ngay từ đầu thì chỉ số sẽ bằng 0. Và giải pháp thứ hai - với giải pháp thông qua StringUtils :
public static String apacheCommonLeftPad(String value) {
return StringUtils.stripStart(value, StringUtils.SPACE + COMMA);
}
Ở đây, chúng tôi chuyển thông tin đối số đầu tiên về chuỗi mà chúng tôi đang làm việc và trong chuỗi thứ hai, chúng tôi chuyển một chuỗi bao gồm các ký tự cần được bỏ qua. Chúng ta tạo lớp StripStartExampleTest theo cách tương tự :
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);
}
}
- phương thức isEmpty
Tất nhiên, phương pháp này đơn giản hơn nhiều, nhưng điều đó không làm nó kém hữu ích hơn chút nào. Nó mở rộng khả năng của phương thức String.isEmpty() , đồng thời bổ sung thêm tính năng kiểm tra giá trị rỗng. Để làm gì? Để tránh NullPointerException, nghĩa là tránh gọi các phương thức gọi trên một biến có giá trị null . Vì vậy, để không viết:
if(value != null && value.isEmpty()) {
//doing something
}
Bạn chỉ có thể làm điều này:
if(StringUtils.isEmpty(value)) {
//doing something
}
Ưu điểm của phương pháp này là có thể biết ngay phương pháp nào được sử dụng.
2. Phân tích các phương thức khác của lớp StringUtils
Bây giờ chúng ta hãy nói về những phương pháp mà theo tôi, cũng đáng được quan tâm. Nói chung về StringUtils , điều đáng nói là nó cung cấp các phương thức an toàn null tương tự như các phương thức được tìm thấy trong lớp String (như trường hợp của phương thức isEmpty ). Chúng ta hãy đi qua chúng:
- phương pháp so sánh
Một phương thức như vậy tồn tại trong Chuỗi và sẽ ném ra một ngoại lệ NullPointerException nếu khi so sánh hai chuỗi, một trong số chúng là null. Để tránh những bước kiểm tra không tốt trong mã của chúng ta, chúng ta có thể sử dụng phương thức StringUtils.compare(String str1, String str2) : nó trả về một int làm kết quả so sánh. Những giá trị này có ý nghĩa gì? int = 0 nếu chúng giống nhau (hoặc cả hai đều rỗng). int < 0, nếu str1 nhỏ hơn str2. int > 0, nếu str1 lớn hơn str2. Ngoài ra, nếu bạn xem tài liệu của họ, Javadoc của phương pháp này trình bày các tình huống sau:
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
- chứa... phương pháp
Ở đây các nhà phát triển tiện ích đã có một sự bùng nổ. Bất cứ phương pháp nào bạn muốn đều có. Tôi quyết định đặt chúng lại với nhau:
-
chứa là một phương thức kiểm tra xem chuỗi dự kiến có nằm trong chuỗi khác hay không. Điều này hữu ích như thế nào? Bạn có thể sử dụng phương pháp này nếu bạn cần đảm bảo rằng có một từ nhất định trong văn bản.
Ví dụ:
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
Một lần nữa, bảo mật NPE (Null Pointer Exception) hiện diện.
containsAny là một phương thức kiểm tra xem có bất kỳ ký tự nào có trong chuỗi hay không. Cũng là một điều hữu ích: bạn thường phải làm điều này. Ví dụ từ tài liệu:
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
-
containsIgnoreCase là một phần mở rộng hữu ích cho phương thức chứa . Thật vậy, để kiểm tra trường hợp như vậy mà không có phương pháp này, bạn sẽ phải thực hiện một số tùy chọn. Và như vậy chỉ có một phương pháp sẽ được sử dụng một cách hài hòa.
-
chứaNone - xét theo tên, bạn có thể hiểu những gì đang được kiểm tra. Không nên có dòng bên trong. Một điều hữu ích, chắc chắn. Tìm kiếm nhanh một số ký tự không mong muốn;). Trong bot điện tín của chúng tôi , chúng tôi sẽ lọc những lời tục tĩu và sẽ không bỏ qua những phương pháp hài hước này.
Và ví dụ, chúng ta sẽ ở đâu nếu không có chúng:
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
Một vài ví dụ từ các tài liệu:
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
- phương thức defaultString
Một loạt các phương pháp giúp tránh thêm thông tin bổ sung nếu chuỗi rỗng và bạn cần đặt một số giá trị mặc định. Có nhiều lựa chọn phù hợp với mọi sở thích. Đứng đầu trong số đó là StringUtils.defaultString(final String str, Final String defaultStr) - trong trường hợp str là null, chúng ta sẽ chỉ chuyển giá trị defaultStr . Ví dụ từ tài liệu:
StringUtils.defaultString(null, "NULL") = "NULL"
StringUtils.defaultString("", "NULL") = ""
StringUtils.defaultString("bat", "NULL") = "bat"
Nó rất thuận tiện khi sử dụng khi bạn tạo lớp POJO bằng dữ liệu.
- phương thức xóa khoảng trắng
Đây là một phương pháp thú vị, mặc dù không có nhiều lựa chọn cho ứng dụng của nó. Đồng thời, nếu trường hợp như vậy xảy ra, phương pháp này chắc chắn sẽ rất hữu ích. Nó loại bỏ tất cả các khoảng trắng khỏi chuỗi. Khoảng cách này ở đâu thì sẽ không có dấu vết của nó))) Ví dụ từ các tài liệu:
StringUtils.deleteWhitespace(null) = null
StringUtils.deleteWhitespace("") = ""
StringUtils.deleteWhitespace("abc") = "abc"
StringUtils.deleteWhitespace(" ab c ") = "abc"
- kết thúcVới phương thức
Nói cho chính nó. Đây là một phương pháp rất hữu ích: nó kiểm tra xem chuỗi có kết thúc bằng chuỗi được gợi ý hay không. Điều này thường là cần thiết. Tất nhiên, bạn có thể tự viết séc, nhưng sử dụng phương pháp làm sẵn rõ ràng sẽ thuận tiện và tốt hơn. Ví dụ:
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
Như bạn có thể thấy, mọi thứ đều kết thúc bằng một dòng trống))) Tôi nghĩ rằng ví dụ này (StringUtils.endsWith("ABCDEF", "") = true) chỉ là một phần thưởng, vì điều này thật vô lý) Ngoài ra còn có một phương pháp bỏ qua trường hợp .
- phương pháp bằng
Một ví dụ tuyệt vời về phương pháp an toàn null để so sánh hai chuỗi. Bất cứ điều gì chúng ta đặt vào đó, câu trả lời sẽ ở đó và sẽ không có lỗi. Ví dụ:
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
Tất nhiên, cũng có EqualsIgnoreCase - mọi thứ được thực hiện theo cách giống hệt nhau, chỉ có điều chúng ta bỏ qua trường hợp này. Hãy xem nào?
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
- phương thức bằng bất kỳ
Hãy tiếp tục và mở rộng phương thức bằng . Giả sử thay vì thực hiện một số kiểm tra đẳng thức, chúng ta muốn thực hiện một kiểm tra. Đối với điều này, chúng ta có thể truyền một chuỗi để so sánh một tập hợp các chuỗi; nếu bất kỳ chuỗi nào trong số chúng bằng chuỗi được đề xuất thì nó sẽ là TRUE. Chúng tôi chuyển một chuỗi và một tập hợp các chuỗi để so sánh chúng với nhau (chuỗi đầu tiên có các chuỗi từ bộ sưu tập). Khó? Dưới đây là ví dụ từ các tài liệu để giúp bạn hiểu ý nghĩa của nó:
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
Ngoài ra còn có EqualsAnyIgnoreCase . Và ví dụ cho nó:
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
Điểm mấu chốt
Kết quả là chúng ta sẽ có kiến thức về StringUtils là gì và nó có những phương thức hữu ích nào. Chà, với việc nhận ra rằng có những thứ hữu ích như vậy và không cần phải chống nạng mỗi lần rào chắn ở những nơi có thể giải quyết vấn đề với sự trợ giúp của một giải pháp làm sẵn. Nói chung, chúng tôi chỉ phân tích một phần của phương pháp. Nếu bạn muốn, tôi có thể tiếp tục: còn rất nhiều người trong số họ nữa và họ thực sự đáng được quan tâm. Nếu bạn có bất kỳ ý tưởng nào về cách trình bày vấn đề này, vui lòng viết thư - Tôi luôn cởi mở với những ý tưởng mới. Tài liệu về các phương pháp được viết rất hay, các ví dụ thử nghiệm kèm theo kết quả được bổ sung, giúp hiểu rõ hơn về hoạt động của phương pháp. Do đó, chúng tôi không ngại đọc tài liệu: nó sẽ xóa tan nghi ngờ của bạn về chức năng của tiện ích. Để có được trải nghiệm viết mã mới, tôi khuyên bạn nên xem cách các lớp tiện ích được tạo và viết. Điều này sẽ hữu ích trong tương lai, vì thông thường mỗi dự án đều có các lớp phế liệu riêng và kinh nghiệm viết chúng sẽ rất hữu ích. Theo truyền thống, tôi khuyên bạn nên đăng ký tài khoản của tôi trên Github ) Đối với những người chưa biết về dự án của tôi với bot telegram, đây là liên kết đến bài viết đầu tiên . Cảm ơn mọi người đã đọc. Tôi đã thêm một số liên kết hữu ích bên dưới.Liên kết hữu ích |
---|
GO TO FULL VERSION