String及StringTable(五):java8的新工具类StringJoiner
在java8中,对于字符串拼接的操作还引入了一个新的类就是StringJoiner,这个类的作用就是提供了一种快捷的字符串拼接的模板方法。
1.使用样例
public static void main(String[] args) {
StringJoiner stringJoiner = new StringJoiner(",","[","]");
stringJoiner.add("a");
stringJoiner.add("b");
stringJoiner.add("c");
stringJoiner.add("d");
System.out.println(stringJoiner.toString());
StringJoiner stringJoiner1 = new StringJoiner(",");
stringJoiner1.add("1").add("2").add("3");
System.out.println(stringJoiner1.toString());
}
其输出如下:
[a,b,c,d]
1,2,3
可以看到,StringJoiner支持传入分隔符、前缀和后缀,之后就能将这种有规律的字符串进行输出。这非常适合我们平时在对数组的print和序列化的过程中。
2.类结构及成员变量
/**
* {@code StringJoiner} is used to construct a sequence of characters separated
* by a delimiter and optionally starting with a supplied prefix
* and ending with a supplied suffix.
* <p>
* Prior to adding something to the {@code StringJoiner}, its
* {@code sj.toString()} method will, by default, return {@code prefix + suffix}.
* However, if the {@code setEmptyValue} method is called, the {@code emptyValue}
* supplied will be returned instead. This can be used, for example, when
* creating a string using set notation to indicate an empty set, i.e.
* <code>"{}"</code>, where the {@code prefix} is <code>"{"</code>, the
* {@code suffix} is <code>"}"</code> and nothing has been added to the
* {@code StringJoiner}.
*
* @apiNote
* <p>The String {@code "[George:Sally:Fred]"} may be constructed as follows:
*
* <pre> {@code
* StringJoiner sj = new StringJoiner(":", "[", "]");
* sj.add("George").add("Sally").add("Fred");
* String desiredString = sj.toString();
* }</pre>
* <p>
* A {@code StringJoiner} may be employed to create formatted output from a
* {@link java.util.stream.Stream} using
* {@link java.util.stream.Collectors#joining(CharSequence)}. For example:
*
* <pre> {@code
* List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
* String commaSeparatedNumbers = numbers.stream()
* .map(i -> i.toString())
* .collect(Collectors.joining(", "));
* }</pre>
*
* @see java.util.stream.Collectors#joining(CharSequence)
* @see java.util.stream.Collectors#joining(CharSequence, CharSequence, CharSequence)
* @since 1.8
*/
public final class StringJoiner {
private final String prefix;
private final String delimiter;
private final String suffix;
/*
* StringBuilder value -- at any time, the characters constructed from the
* prefix, the added element separated by the delimiter, but without the
* suffix, so that we can more easily add elements without having to jigger
* the suffix each time.
*/
private StringBuilder value;
/*
* By default, the string consisting of prefix+suffix, returned by
* toString(), or properties of value, when no elements have yet been added,
* i.e. when it is empty. This may be overridden by the user to be some
* other value including the empty String.
*/
private String emptyValue;
}
StringJoiner这个类比较单一,就是一个简单的工具类,没有实现任何接口,继承任何父类。其注释大意为: StringJoiner根据分隔符、前缀、后缀来构造分隔的字符串。 在调用add方法添加内容之后,他在默认的情况下是返回前缀+分隔符组合字符串+后缀。但是如果调用setEmptyValue方法之后,如果value为空,将会返回这个设置的字符串。 StringJoiner已经被Collectors引用,在Stream处理中,我们可以类似这样使用:
* java.util.stream.Collectors#joining(CharSequence)
* java.util.stream.Collectors#joining(CharSequence, CharSequence, CharSequence)
主要的成员变量有5个,分别是String类型的前缀prefix,分隔符delimiter、后缀suffix,实际上内部是一个StringBuilder value,字符串拼接操作采用StringBuilder来完成。还有一个当value为空的时候的默认字符串emptyValue。
2.构造函数
StringJoiner提供的构造函数有两个,分别是只有分隔符的构造函数:
public StringJoiner(CharSequence delimiter) {
this(delimiter, "", "");
}
和另外一个提供了前后缀的:
public StringJoiner(CharSequence delimiter,
CharSequence prefix,
CharSequence suffix) {
Objects.requireNonNull(prefix, "The prefix must not be null");
Objects.requireNonNull(delimiter, "The delimiter must not be null");
Objects.requireNonNull(suffix, "The suffix must not be null");
// make defensive copies of arguments
this.prefix = prefix.toString();
this.delimiter = delimiter.toString();
this.suffix = suffix.toString();
this.emptyValue = this.prefix + this.suffix;
}
实际上可以看出第一个构造函数只是将前后缀设置为空了,还是使用的第二个构造函数。 对于第二个构造函数,emptyValue默认等于前缀加后缀。
3.其他方法
3.1 setEmptyValue
由于前文提到了emptyValue,那么首先提供了一个setEmptyValue方法:
public StringJoiner setEmptyValue(CharSequence emptyValue) {
this.emptyValue = Objects.requireNonNull(emptyValue,
"The empty value must not be null").toString();
return this;
}
3.2 toString
public String toString() {
if (value == null) {
return emptyValue;
} else {
if (suffix.equals("")) {
return value.toString();
} else {
int initialLength = value.length();
String result = value.append(suffix).toString();
// reset value to pre-append initialLength
value.setLength(initialLength);
return result;
}
}
}
判断只要value为null则返回emptyValue。之后判断后缀是否为空。否则在value上加上后缀。
3.3 add
public StringJoiner add(CharSequence newElement) {
prepareBuilder().append(newElement);
return this;
}
这是主要的添加元素的方法。
3.4 merge
提供了将两个StringJoiner合并的merge方法:
public StringJoiner merge(StringJoiner other) {
Objects.requireNonNull(other);
if (other.value != null) {
final int length = other.value.length();
// lock the length so that we can seize the data to be appended
// before initiate copying to avoid interference, especially when
// merge 'this'
StringBuilder builder = prepareBuilder();
builder.append(other.value, other.prefix.length(), length);
}
return this;
}
3.5 prepareBuilder
添加前缀的方法:
private StringBuilder prepareBuilder() {
if (value != null) {
value.append(delimiter);
} else {
value = new StringBuilder().append(prefix);
}
return value;
}
3.5 length
得到整个串的长度:
public int length() {
// Remember that we never actually append the suffix unless we return
// the full (present) value or some sub-string or length of it, so that
// we can add on more if we need to.
return (value != null ? value.length() + suffix.length() :
emptyValue.length());
}
如果不为空,由于后缀是在toString的时候才添加的,没有加上后缀,因此长度中需要将后缀的长度加上。
- Spark自定义累加器的实现
- 每天学习一点儿算法--二分查找
- IntelliJ IDEA两种keymap快捷键方案Mac OS X和Mac OS X 10.5+的区别
- Apache Avro是什么干什么用的(RPC/序列化)
- 萌新刷题(十二)二叉树的前序遍历
- 轻松掌握ES6中集合Set的用法
- 萌新刷题(十三)买卖股票的最佳时机
- 萌新刷题(十一)有效数字
- Hive性能优化统计每日IP CREATE TABLE ip_2014_12_29 AS SELECT COUNT(DISTINCT ip) AS IP FROM logdfs WHERE logda
- 算法中描述复杂度的大O是什么意思?
- 优化Mysql:3个简单的调整
- Redis的5个常见应用场景
- Mysql 索引你了解多少?
- Mysql 8 新特性 window functions 有什么用?
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 用Python里面的Xpath完成一个在线汇率转换器
- 详解请求消息 resquest
- Android中窗口Input事件接收
- Linux下常用命令
- Cypress系列(53)- as() 命令详解
- Educational Codeforces Round 81 (Rated for Div. 2) A. Display The Number
- Cypress系列(55)- 设置全局 URL
- Linux不同共享库中同名函数的处理
- Cypress系列(56)- 避免访问多个站点
- Cypress系列(57)- 删除等待代码
- DOM 又是个什么鬼?
- Cypress系列(58)- 停用条件测试
- 会python真的可以为所欲为——爆破前端加密登录
- XML 出来接客了!
- Cypress系列(59)- 实时调试和中断