Java 字符串操作

常见的字符串操作问题

字符串分割


JDK中的split行为有点怪,如果分割出的空串在末尾,就会删掉

1
"a,b,,c,,".split(",");  //[a, b, , c]

commons-lang中StringUtils的split会把相邻的多个分隔符认为是一个,因此不会出现空串

1
StringUtils.split("a,b,,c,,", ","); //[a, b, c]

很多情况下需要保持空串,要不会导致索引对不上,可以调用splitPreserveAllTokens

1
StringUtils.splitPreserveAllTokens("a,b,,c,,", ",") //[a, b, , c, , ]

字符串拼接


+的背后是StringBuilder,如果拼接的字符串很多,那么StringBuilder有优势

1
2
3
String a = "foo";
String b = "bar";
String c = a + b;
1
2
3
4
StringBuilder sb = new StringBuilder();
sb.append(a);
sb.append(b);
String c = sb.toString();

但是如果只是两个字符串拼接,那么创建StringBuilder就有点浪费,直接使用String#contact方法

1
String c = a.contact(b);

上述方法都是针对字符变量而言,如果是常量,直接使用+反而最快,因为直接在编译期优化,运行时已经合为一体

1
String helloWorld = "hello"+"world";

如果在循环中使用+进行连续拼接,那么每次循环都会生成独立的StringBuilder,此时需要在循环外显式操作StringBuilder,并且如果能提前预知结果大小,提前分配容量可以提升性能

移除前后缀


前后缀相同

1
StringUtils.strip("foobarfoo","foo"); //bar

还可移除单侧,即相当于前后缀

1
2
StringUtils.removeStart("foobarfoo","foo"); //barfoo
StringUtils.removeEnd("foobarfoo","foo"); //foobar

替换


替换次数控制

1
StringUtils.replace("foobarfoo","o","e",2); //feebarfoo

循环替换

1
StringUtils.replaceRepeatedly();

子串


负索引

1
StringUtils.substring("abc", -2) = "bc"

更多便利语义

1
2
3
StringUtils.left("abc", 2)   = "ab"
StringUtils.right("abc", 2) = "bc"
StringUtils.mid("abcd", 1, 2) = "bc"

中间提取


相同,不同

1
2
StringUtils.substringBetween("'abc'", "'") //abc
StringUtils.substringBetween("<abc>", "<",">") //abc

全结果返回

1
StringUtils.substringsBetween("<abc><def>", "<",">") = //[abc,def]

定位


JDK indexOf返回一个位置

正数倒数位置
ordinalIndexOf
lastIndexOf

定位后丢弃


commons-lang

1
2
StringUtils.substringBefore("aaa@bbb@ccc", "@"); //aaa
StringUtils.substringBeforeLast("aaa@bbb@ccc", "@"); //aaa@bbb

默认值


commons-lang

1
2
StringUtils.default(null, "foo");
StringUtils.defaultIfEmpty("", "foo");