【JDK源码分析】 String.join()方法解析

前言

最近出于习惯问题,顺手点开了String的源码,意外发现String在JDK 8中新增了join方法。(实在惭愧,JDK 8都发布多久了。。。)

源码

String重载了join方法,两个方法的异同点在于,第一个方法使用的可变参数,第二个方法使用的可迭代参数,这样设计主要是为了方法适用性更广。比如参数可以传一个数组、集合等等。下面就拿一个方法的源码来解析
String 类

     /**
     * delimiter 分隔符
     * elements 需要连接的字符数组
     */
    public static String join(CharSequence delimiter, CharSequence... elements) {
        // 空指针判断
        Objects.requireNonNull(delimiter);
        Objects.requireNonNull(elements);

        // Number of elements not likely worth Arrays.stream overhead.
        // 此处用到了StringJoiner(JDK 8引入的类)
        // 先构造一个以参数delimiter为分隔符的StringJoiner对象
        StringJoiner joiner = new StringJoiner(delimiter);
        for (CharSequence cs: elements) {
            // 拼接字符
            joiner.add(cs);
        }
        return joiner.toString();
    }

查看StringJoiner源码

    // 前缀
    private final String prefix;
    // 分隔符
    private final String delimiter;
    // 后缀
    private final String suffix;
    //
    private StringBuilder value;

    /**
    * 构造器
    */
    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;
    }

    // 拼接
    public StringJoiner add(CharSequence newElement) {
        prepareBuilder().append(newElement);
        return this;
    }

    // 预拼接value
    private StringBuilder prepareBuilder() {
        // value已加前缀
        if (value != null) {
            // 此时添加分隔符
            value.append(delimiter);
        } else {
            // value未加前缀时需要先添加前缀
            value = new StringBuilder().append(prefix);
        }
        return value;
    }

    //重写了toString 方法
    @Override
    public String toString() {
        if (value == null) {
            // value未进行任何字符拼接时反悔emptyValue
            return emptyValue;
        } else {
            // 后缀为""字符时,直接返回value
            if (suffix.equals("")) {
                return value.toString();
            } else {
                // 获取value未拼接后缀的长度
                int initialLength = value.length();
                String result = value.append(suffix).toString();
                // reset value to pre-append initialLength
                // 此处是为了保证value.toString()为未拼接后缀前的字符串         
                value.setLength(initialLength);
                return result;
            }
        }
    }   
使用方式
        String delimiter = "-";
        String[] elements = {"JDK", "8", "String", "join"};
        List<String> list = new ArrayList<String>(Arrays.asList(elements));

        System.out.println(String.join(delimiter, elements));
        System.out.println(String.join(delimiter, "JDK", "8", "String", "join"));
        System.out.println(String.join(delimiter, list));

输出结果
输出结果

 

posted @ 2018-07-18 22:38  还是搬砖踏实  阅读(529)  评论(0编辑  收藏  举报