jdk8中字符串拼接神器:StringJoiner

前言
在平时编码中经常涉及到字符串的拼接,也在代码review中经常看到字符串的拼接,很多时候都是简单粗暴的使用string+=‘’,即性能低也不美观,代码易读性也差,今天就推荐一个jdk8的字符串拼接工具类:StringJoiner,虽然jdk8已经使用很多年了,但是很多程序员对它的特性使用很少,不少同学都是够用即可,对我们开发者来说应该要有探索精神;

介绍
1.常见的字符串拼接方式
1)在string中使用+=进行字符串拼接;

String sb = "";
        for (int i = 0; i < 10; i++) {
            sb += i + ",";
        }
        System.out.println(sb);
 结果:0,1,2,3,4,5,6,7,8,9,

2)使用StringBuffer
我相信很多同学使用StringBuffer拼接字符串的原因是性能高、线程安全的,但是还是复杂了一些;

  StringBuilder sb = new StringBuilder();
        IntStream.range(1,10).forEach(i->{
            sb.append(i+"");
            if( i < 10){
                sb.append(",");
            }
        });
        System.out.println(sb);
        
结果:1,2,3,4,5,6,7,8,9,

StringJoiner使用:

1)StringJoiner类的构造函数,可以自定义的前缀开始和自定义的后缀结尾,比较灵活和实用。

//值依次是分割符 , 前缀  ,后缀
StringJoiner stringJoiner = new StringJoiner(",", "[", "]");
        stringJoiner.add("java");
        stringJoiner.add("php");
        System.out.println(stringJoiner.toString());  
        
 结果:[java,php]
 

2)StringJoiner在处理sql拼接上面,也非常方便,如拼接 sql 的in条件的时候:

StringJoiner joiner3 = new StringJoiner("','", "'", "'");
joiner3.add("java").add("php");
结果:'java','php'

注:这个创建我们使用的还是比较多的

源码分析
想要更多的了解StringJoiner 类,还是需要分析源码,类的源码比较通俗易懂,StringJoiner 更像一个装饰者模式,对外隐藏了StringBuilder。
不过需要注意的是 StringJoiner 并且没有处理一些基本的集合元素情况,比如加入列表的元素,更像针对Collectors而设计。

package java.util;

public final class StringJoiner {
    private final String prefix;//前缀
    private final String delimiter;//间隔符
    private final String suffix;//后缀
    private StringBuilder value;//值

    private String emptyValue;//空值

    public StringJoiner(CharSequence delimiter) {
        this(delimiter, "", "");
        //默认前缀和后缀为"",重载调用
    }

    public StringJoiner(CharSequence delimiter,
                        CharSequence prefix,
                        CharSequence suffix) {
        //间隔符,前缀和后缀判断是否为null,null将抛出异常
        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"); 
        // 成员变量赋值
        this.prefix = prefix.toString();
        this.delimiter = delimiter.toString();
        this.suffix = suffix.toString();
        this.emptyValue = this.prefix + this.suffix;//空值被设置为只有前后缀
    }
 //设置空值,检查是否为null
    public StringJoiner setEmptyValue(CharSequence emptyValue) {
        this.emptyValue = Objects.requireNonNull(emptyValue,
            "The empty value must not be null").toString();
        return this;
    }

    @Override
    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;
            }
        }
    }
    //初始化,先添加前缀,有了之后每次先添加间隔符,StringBuilder后续append字符串
    public StringJoiner add(CharSequence newElement) {
        prepareBuilder().append(newElement);
        return this;
    }
 //合并StringJoiner,注意后面StringJoiner 的前缀就不要了,后面的appen进来
    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;
    }
 //初始化,先添加前缀,添加之后每次先添加间隔符
    private StringBuilder prepareBuilder() {
        if (value != null) {
            value.append(delimiter);
        } else {
            value = new StringBuilder().append(prefix);
        }
        return value;
    }

    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());
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dylan~~~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值