你还不会使用Guava处理字符串? 那你还不进来学习?
Posted c.
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你还不会使用Guava处理字符串? 那你还不进来学习?相关的知识,希望对你有一定的参考价值。
你还不会使用Guava处理字符串? 那你还不进来学习?
连接器[Joiner]
用分隔符把字符串序列连接起来也可能会遇上不必要的麻烦。如果字符串序列中含有null,那连接操作会更难。但是连接器Joiner让我们连接字符串变得更加简单
比如我们现在一个字符串的集合,然后我们需要用‘#’来把这个集合中的数据连接起来,用Joiner怎么做呢?
public class JoinerTest {
private final List<String> stringList = Arrays.asList("Google", "Guava", "Java", "Scala", "Kafka");
@Test
public void testJoinOnJoin() {
String result = Joiner.on("#").join(stringList);
Assertions.assertEquals("Google#Guava#Java#Scala#Kafka", result);
}
}
通过Joiner.on("#").join(stringList);
就可以把一个集合通过某个连接符来连接成字符串
那如果现在我们的集合中包含null
,该如何处理,正常我们写程序可能会没考虑到这种空指针的问题。
public class JoinerTest {
private final List<String> stringListWithNullValue = Arrays.asList("Google", "Guava", "Java", "Scala", null);
@Test
public void testJoinOnJoinWithNullValue() {
assertThrows(NullPointerException.class, () -> {
String result = Joiner.on("#").join(stringListWithNullValue);
});
}
}
比如如果用Joiner.on("#").join(stringListWithNullValue)
,对于集合中有null
的情况是会报空指针异常的,那种情况我们要怎么处理?
我们可以通过skipNulls()
来过滤掉集合中的null
元素。
public class JoinerTest {
private final List<String> stringListWithNullValue = Arrays.asList("Google", "Guava", "Java", "Scala", null);
@Test
public void testJoinOnJoinWithNullValueButSkip() {
String result = Joiner.on("#").skipNulls().join(stringListWithNullValue);
Assertions.assertEquals("Google#Guava#Java#Scala", result);
}
}
而且通过这种Fluent风格的Joiner让连接字符串更简单。
那再比如说,我们有个要求是当集合元素有null
元素的时候,我们需要用默认值去代替,该怎么做呢?
package org.example.joiner;
import com.google.common.base.Joiner;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class JoinerTest {
private final List<String> stringListWithNullValue = Arrays.asList("Google", "Guava", "Java", "Scala", null);
@Test
public void testJoin_On_Join_WithNullValue_UseDefaultValue() {
String result = Joiner.on("#").useForNull("DEFAULT").join(stringListWithNullValue);
Assertions.assertEquals("Google#Guava#Java#Scala#DEFAULT", result);
}
}
我们可以使用useForNull("默认代替的字符串")
来完成连接。
public class Joiner {
public static Joiner on(String separator) {
return new Joiner(separator);
}
public static Joiner on(char separator) {
return new Joiner(String.valueOf(separator));
}
}
Joiner的on
方法总会返回一个新的joiner实例。这使得joiner实例都是线程安全的
使用的方式还有很多,还可以把集合连接后返回一个StringBuilder
对象
@Test
public void testJoin_On_Append_To_StringBuilder() {
final StringBuilder builder = new StringBuilder();
StringBuilder resultBuilder = Joiner.on("#").useForNull("DEFAULT").appendTo(builder, stringListWithNullValue);
assertSame(resultBuilder,builder);//传入的对象和返回出来的对象是同一个对象
assertEquals("Google#Guava#Java#Scala#DEFAULT",resultBuilder.toString());
assertEquals("Google#Guava#Java#Scala#DEFAULT",builder.toString());
}
当然还可以把集合连接后写入一个文件流中
@Test
public void testJoin_On_Append_To_Writer() {
final String targetFileName = "guava-joiner.txt";
try (FileWriter writer = new FileWriter(new File(targetFileName))) {
Joiner.on("#").useForNull("DEFAULT").appendTo(writer, stringListWithNullValue);
assertTrue(Files.isFile().test(new File(targetFileName)));
} catch (IOException e) {
fail("append to the writer occur fetal error.");
}
}
题外话题,现在我们考虑一下,如果不用Guava的Joiner我们平时该怎么处理这种字符串的连接呢?其实利用java8也是可以很快实现的,只是没有Guava这么简单便捷。
public class JoinerTest {
private final List<String> stringListWithNullValue = Arrays.asList("Google", "Guava", "Java", "Scala", null);
@Test
public void testJoiningByStreamWithDefaultValue() {
String result = stringListWithNullValue.stream().map(this::defaultValue).collect(joining("#"));
assertEquals("Google#Guava#Java#Scala#DEFAULT", result);
}
private String defaultValue(final String item) {
return item == null || item.isEmpty() ? "DEFAULT" : item;
}
}
还有对于map这种key,value形式,Guava的Joiner可以用withKeyValueSeparator
方法进行连接。
@Test
public void testJoinOnWithMap() {
final Map<String, String> stringMap = of("Hello", "Guava", "Java", "Scala");
assertEquals("Hello=Guava#Java=Scala", Joiner.on('#').withKeyValueSeparator("=").join(stringMap));
}
拆分器[Splitter]
JDK内建的字符串拆分工具有一些古怪的特性。比如,String.split悄悄丢弃了尾部的分隔符。 问题:
”,a, ,b,”.split(“,”)
返回什么呢?
package org.example.splitter;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class SplitterTest {
@Test
public void test_string_split() {
String str = ",a, ,b,";
String[] split = str.split(",");
assertEquals(4, split.length);
assertEquals("[, a, , b]", Arrays.toString(split));
}
}
所以这不是我们期望的结果,我们期望的结果只是需要拿到a和b两个字符,那如果通过Guava的Splitter,我们就可以很容易的做到。
@Test
public void testSplitOnSplit() {
List<String> result = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(",a, ,b,");
assertEquals(2,result.size());
assertEquals("a",result.get(0));
assertEquals("b",result.get(1));
}
看到了吧,这就是Splitter的厉害之处。再继续看多几个例子
@Test
public void testSplit_On_Split_OmitEmpty() {
List<String> result = Splitter.on("|").splitToList("hello|world|||");
assertNotNull(result);
assertEquals(5, result.size());
//过滤掉split之后的空字符串
result = Splitter.on("|").omitEmptyStrings().splitToList("hello|world|||");
assertNotNull(result);
assertEquals(2, result.size());
}
@Test
public void testSplit_On_Split_OmitEmpty_TrimResult() {
List<String> result = Splitter.on("|").omitEmptyStrings().splitToList("hello | world|||");
assertNotNull(result);
assertEquals(2, result.size());
assertEquals("hello ", result.get(0));
assertEquals(" world", result.get(1));
//过滤掉split之后的空字符串并把结果进行trim操作
result = Splitter.on("|").trimResults().omitEmptyStrings().splitToList("hello | world|||");
assertEquals("hello", result.get(0));
assertEquals("world", result.get(1));
}
@Test
public void testSplitFixLength() {
//还可以按照长度进行分割
List<String> result = Splitter.fixedLength(4).splitToList("aaaabbbbccccdddd");
assertNotNull(result);
assertEquals(4, result.size());
assertEquals("aaaa", result.get(0));
assertEquals("bbbb", result.get(1));
assertEquals("cccc", result.get(2));
assertEquals("dddd", result.get(3));
}
@Test
public void testSplitOnSplitLimit() {
//限制分割后的结果集个数
List<String> result = Splitter.on("#").limit(3).splitToList("hello#world#java#google#scala");
assertNotNull(result);
assertEquals(3, result.size());
assertEquals("hello", result.get(0));
assertEquals("world", result.get(1));
assertEquals("java#google#scala", result.get(2));
}
@Test
public void testSplitOnSplitLimit() {
//限制分割后的结果集个数
List<String> result = Splitter.on("#").limit(3).splitToList("hello#world#java#google#scala");
assertNotNull(result);
assertEquals(3, result.size());
assertEquals("hello", result.get(0));
assertEquals("world", result.get(1));
assertEquals("java#google#scala", result.get(2));
}
@Test
public void testSplitOnPatternString() {
//还可以按照正则表达式分割
List<String> result = Splitter.onPattern("\\\\|").trimResults().omitEmptyStrings().splitToList("hello | world|||");
assertNotNull(result);
assertEquals(2,result.size());
assertEquals("hello",result.get(0));
assertEquals("world",result.get(1));
}
@Test
public void testSplitOnPattern() {
List<String> result = Splitter.on(Pattern.compile("\\\\|")).trimResults().omitEmptyStrings().splitToList("hello | world|||");
assertNotNull(result);
assertEquals(2,result.size());
assertEquals("hello",result.get(0));
assertEquals("world",result.get(1));
}
@Test
public void testSplitOnSplitToMap() {
Map<String, String> result = Splitter.on(Pattern.compile("\\\\|")).trimResults()
.omitEmptyStrings().withKeyValueSeparator("=").split("hello=HELLO| world=WORLD|||");
assertNotNull(result);
assertEquals(2,result.size());
assertEquals("HELLO",result.get("hello"));
assertEquals("WORLD",result.如果你还不知道如何控制springboot中bean的加载顺序,那你一定要看此篇