greenlaw110 / blog

support writing blogs
0 stars 0 forks source link

OSGL - The art of String processing #3

Open greenlaw110 opened 6 years ago

greenlaw110 commented 6 years ago

在 [OSGL 工具库 - 图片处理的艺术] (https://my.oschina.net/greenlaw110/blog/1786151) 中我们介绍了如何通过 OSGL Img 提供的一套 API 流畅地处理图片, 例如:

source(img1())
        .resize(300, 400)
        .pipeline()
        .crop(50, 50, 250, 350)
        .pipeline()
        .watermark("HELLO OSGL")
        .writeTo("/tmp/img1_pipeline.png");

采用这种方式编写的代码极大地提高了可读性, 我们把这种 API 结构称为流式编程 (Fluent Programming). 我们在本文中将介绍如何使用 OSGL S 库处理字串, 包括采用流式编程来提供具有高可读性的字串处理代码.

下面用代码来说明一切:

1. 字串判断

1.1 判断字串是否为空

boolean b = S.isEmpty(""); // true
b = S.isEmpty(null); // true
b = S.isEmpty(" "); // false
b = S.isBlank(" "); // true
b = S.isNotEmpty("abc"); // true
b = S.isNotBlank("\t"); false
b = S.isAnyEmpty("", "xyz", ..); // true
b = S.isAllEmpty("", "xyz", ...); // false

1.2. 判断字串是否为数字

boolean b = S.isIntOrLong("12345"); // true
b = S.isIntOrLong("1234.5"); // false
b = S.isNumeric("1234.5"); // true

1.3 字串判断的流式编程

boolean b = S.is("foo").empty(); // false
b = S.is(" ").blank(); // true
b = S.is("abc").contains("ab"); // true
b = S.is("abc").startsWith("ab"); // true
b = S.is("abc").endsWith("ab"); // false
b = S.is(null).equalsTo(null); // true
b = S.is(null).equalsTo(""); // true
b = S.is(null).equalsTo(" "); // false
b = S.is("[abc]").wrappedWith("[", "]"); // true
b = S.is("<abc>").wrappedWith(S.ANGLE_BRACKETS); // true

2. 字串相等性

yes(S.eq("foo", "foo"));
yes(S.eq("foo", "Foo", S.IGNORECASE));
no(S.eq("foobar", " FooBar "));
yes(S.eq("foobar", " FooBar ", S.IGNORESPACE | S.IGNORECASE));
yes(S.eq(null, null));
no(S.eq(null, "foo"));

3. 字串格式化

String s = S.fmt("hello %s", "world"); // hello world
s = S.msgFmt("hello {0}", "world"); // hello world

4. 字串验证

String s = S.requireNotEmpty("foo"); // foo
s = S.requireNotBlank("bar"); // bar
s = S.requireNotEmpty(""); // raise IllegalArgumentException
s = S.requireNotBlank("  "); raise IllegalArgumentException

5. 字串长度

int n = S.len("abc"); // 3
n = S.len(null); // 0

6. 字串分割

List<String> list = S.fastSplit("/tmp/foo/bar", "/"); [tmp, foo, bar]
S.List list = S.split("abc5xyz132ijk", ":"); [abc, xyz, ijk]
list = S.split("/tmp/foo/bar").by("/").get(); [tmp, foo, bar]
list = S.split("[abc]-[xyz]").by("-").stripElementWrapper(S.BRACKETS).get(); // [abc, xyz]

7. 字串拼接

7.1 集合拼接为字串

List<String> list = C.list("abc", "xyz");
String s = S.join(list).by("-").get(); // abc-xyz
s = S.join(list).by("-").wrapElementWith(S.SQUARE_BRACKETS).get(); // [abc]-[xyz]
list = S.list("abc", null, "xyz");
S.join(list).by("-").get(); // abc--xyz
S.join(list).by("-").ignoreEmptyElement().get(); // abc-xyz

7.2 任意类型对象拼接为字串

String s = S.concat("abc", 123); // abc123
s = S.concat("abc", null, 123); // abc123

7.3 路径拼接

eq("foo/bar", S.pathConcat("foo", '/', "bar"));
eq("foo/bar", S.pathConcat("foo/", '/', "bar"));
eq("foo/bar", S.pathConcat("foo", '/', "/bar"));
eq("foo/bar", S.pathConcat("foo/", '/', "/bar"));

9. 字串修饰确认

eq("[abc]", S.ensure("abc").wrappedWith(S.SQUARE_BRACKETS));
eq("[abc]", S.ensure("[abc").wrappedWith(S.SQUARE_BRACKETS));
eq("[abc]", S.ensure("[abc]").wrappedWith(S.SQUARE_BRACKETS));
eq("abc", S.ensure("abc").strippedOff(S.ANGLE_BRACKETS));
eq("abc", S.ensure("<abc>").strippedOff(S.ANGLE_BRACKETS));
eq("_abc", S.ensure("abc").startWith('_'));
eq("abc.html", S.ensure("abc").endWith(".html"));

10. 字串替换

String s;
s = S.given("hello world").replace("world").with("foo"); // hello foo
s = S.replace("world").in("hello world").with("foo"); // hello foo
s = S.replace("world").with("foo").in("hello world"); // hello foo
s = S.replace("[0-9]+").with("[N]").usingRegEx().in("times 10")); // times [N]

11. 字串重复

eq("aaa", S.repeat('a').times(3));
eq("aaa", S.repeat('a').x(3));
eq("aaaaa", S.repeat('a').forFiveTimes());
eq("foofoo", S.repeat("foo").times(2));
eq("foofoo", S.repeat("foo").x(2));

12. 字串包裹

eq("*abc*", S.wrap("abc").with("*"));
eq("[abc]", S.wrap("abc").with("[", "]"));
eq("[abc]", S.wrap("abc").with(S.BRACKETS));
eq("(abc)", S.wrap("abc").with(S.PARENTHESES));
eq("<abc>", S.wrap("abc").with(S.DIAMOND));
eq("<abc>", S.wrap("abc").with(S.ANGLE_BRACKETS));
eq("《abc》", S.wrap("abc").with(S.书名号));

13. 字串去包裹

eq("abc", S.strip("[abc]").of(S.BRACKETS));
eq("abc", S.strip("<abc>").of(S.DIAMOND));
eq("abc", S.strip("*abc*").of("*"));
eq("abc", S.strip("111abc222").of("111", "222"));

14. 字串切断

eq("abc12", S.cut("abc123").by(5));
eq("ab", S.cut("abc123").first(2));
eq("23", S.cut("abc123").last(2));
eq("123", S.cut("abc123").after("abc"));
eq("abc", S.cut("abc123").before("123"));
eq("abc", S.cut("abc123abc123").before("123"));
eq("abc", S.cut("abc123abc123").beforeFirst("123"));
eq("abc123abc", S.cut("abc123abc123").beforeLast("123"));
eq("123", S.cut("abc123abc123").after("abc"));
eq("123", S.cut("abc123abc123").afterLast("abc"));
eq("123abc123", S.cut("abc123abc123").afterFirst("abc"));

15. 关键字处理

final String s = "Hello World";
eq("HelloWorld", S.camelCase(s));
eq("hello_world", S.underscore(s));
eq("hello-world", S.dashed(s));
eq("Hello World", S.capFirst(s));
eq("hello World", S.lowerFirst(s));
eq("Hello-World", Keyword.of(s).httpHeader());
eq("helloWorld", Keyword.of(s).javaVariable());
eq("HELLO_WORLD", Keyword.of(s).constantName());
eq("Hello world", Keyword.of(s).readable());

16. 子串计数

final String s = "1011101111";
eq(3, S.count("11").in(s));
eq(5, S.count("11").withOverlap().in(s));

17. 其他工具

eq("", S.trim(null));
eq("abc", S.trim(" abc"));
eq("abc\nxyz", S.dos2unix("abc\n\rxyz"));
eq("abc\n\rxyz", S.unix2dos("abc\nxyz"));
eq("this...", S.maxLength("this is a long text", 4));
yes(S.eq("foo", "foo"));
String s;
s = S.uuid(); // 9b2ec83d-15df-4746-9689-c82df5643832
s = S.random(); //kGYH$KCj
s = S.random(2); // gb
s = S.maxLength("this is a long text", 4); // this...