StringJoiner

  • 属性说明
/**
* StringJoiner 使用指定的分割符将多个字符串进行拼接,并可指定前缀和后缀
*
* @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; /** 持续添加的字符串数组 */
private String[] elts; /** 已添加的字符串个数 */
private int size; /** 所有字符串的总长度,包括前缀和后缀 */
private int len; /**
* 空值
*
* When null, prefix + suffix is used as the empty value.
*/
private String emptyValue;
  • 实例化
    /**
* 创建分割符为 delimiter,前缀和后缀都为 "" 的 StringJoiner 对象
*
* @param delimiter 分割符
*/
public StringJoiner(CharSequence delimiter) {
this(delimiter, "", "");
} /**
* 创建指定分割符、前缀、后缀的 StringJoiner
*
* @param delimiter 用于连接字符串的分隔符
* @param prefix 前缀字符序列
* @param suffix 后缀字符序列
*/
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();
}
  • 追加字符串
    /**
* 追加字符串 newElement 到此 StringJoiner 中
*
* @param newElement 追加的新元素
*/
public StringJoiner add(CharSequence newElement) {
final String elt = String.valueOf(newElement);
// 1)创建长度为 8 的初始缓冲区
if (elts == null) {
elts = new String[8];
} else {
// 如果已满,则执行双倍扩容
if (size == elts.length) {
elts = Arrays.copyOf(elts, 2 * size);
}
// 记录总字符数
len += delimiter.length();
}
// 记录总字符数
len += elt.length();
// 写入目标元素
elts[size++] = elt;
return this;
}
  • 返回此 StringJoiner 的字符串表示
    /**
* 返回此 StringJoiner 的字符串表示
*/
@Override
public String toString() {
final String[] elts = this.elts;
// 1)尝试返回空值
if (elts == null && emptyValue != null) {
return emptyValue;
}
final int size = this.size;
final int addLen = prefix.length() + suffix.length();
// 如果未指定前缀和后缀
if (addLen == 0) {
// 完成字符串拼接
compactElts();
return size == 0 ? "" : elts[0];
}
final String delimiter = this.delimiter;
final char[] chars = new char[len + addLen];
int k = getChars(prefix, chars, 0);
if (size > 0) {
k += getChars(elts[0], chars, k);
for (int i = 1; i < size; i++) {
k += getChars(delimiter, chars, k);
k += getChars(elts[i], chars, k);
}
}
k += getChars(suffix, chars, k);
return new String(chars);
} private void compactElts() {
// 完成字符串拼接
if (size > 1) {
final char[] chars = new char[len];
// 写入第一个字符串
int i = 1, k = getChars(elts[0], chars, 0);
do {
// 写入分割符
k += getChars(delimiter, chars, k);
// 写入后一个字符串
k += getChars(elts[i], chars, k);
elts[i] = null;
} while (++i < size);
size = 1;
elts[0] = new String(chars);
}
}

StringJoiner 源码阅读的更多相关文章

  1. 【原】FMDB源码阅读(三)

    [原]FMDB源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 FMDB比较优秀的地方就在于对多线程的处理.所以这一篇主要是研究FMDB的多线程处理的实现.而 ...

  2. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  3. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  4. 【原】AFNetworking源码阅读(六)

    [原]AFNetworking源码阅读(六) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 这一篇的想讲的,一个就是分析一下AFSecurityPolicy文件,看看AF ...

  5. 【原】AFNetworking源码阅读(五)

    [原]AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTP ...

  6. 【原】AFNetworking源码阅读(四)

    [原]AFNetworking源码阅读(四) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇还遗留了很多问题,包括AFURLSessionManagerTaskDe ...

  7. 【原】AFNetworking源码阅读(三)

    [原]AFNetworking源码阅读(三) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇的话,主要是讲了如何通过构建一个request来生成一个data tas ...

  8. 【原】AFNetworking源码阅读(二)

    [原]AFNetworking源码阅读(二) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中我们在iOS Example代码中提到了AFHTTPSessionMa ...

  9. 【原】AFNetworking源码阅读(一)

    [原]AFNetworking源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 AFNetworking版本:3.0.4 由于我平常并没有经常使用AFNetw ...

随机推荐

  1. Linux命令详解——vmstat

    Vmstat命令详解 一.前言 vmstat命令:  用来获得有关进程.虚存.页面交换空间及 CPU活动的信息.这些信息反映了系统的负载情况 二.虚拟内存运行原理 在系统中运行的每个进程都需要使用到内 ...

  2. Delphi ActiveX编程

    樊伟胜

  3. 蓝牙App漏洞系列分析之三CVE-2017-0645

    蓝牙App漏洞系列分析之三CVE-2017-0645 0x01 漏洞简介 Android 6月的安全公告,同时还修复了我们发现的一个蓝牙 App 提权中危漏洞,该漏洞允许手机本地无权限的恶意程序构造一 ...

  4. angular打印功能实现方式

    目前主流的前端打印方式有两种:一种是使用浏览器打印功能直接打印页面,另一种是调用本地控件实现.浏览器打印功能单一,不适用于复杂的业务表单,而打印控件可以设计打印模板,实现复杂表单的打印,十分适合复杂的 ...

  5. 在RecyclerView中集成QQ汽泡二

    上次已经将GooView集成到RecyclerView当中了[http://www.cnblogs.com/webor2006/p/7787511.html],但是目前还有很多问题,下面先来运行看一下 ...

  6. inclusion_tag模块

    目录 inclusion_tag模块 inclusion_tag模块 1.当页面上某一块区域的内容需要在多个页面上展示的使用,并且该区域的内容需要通过传参数才能正常显示,那么我们可以优先考虑inclu ...

  7. hive中的 lateral view

    lateral view用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合. 一个简单的例子,假设我们有一张表pageAds,它有 ...

  8. 【Python网络】HTTP

    HTTP概述 HTTP(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器和万维网服务器之间互相通信的规则. HTTP就是一个通信规则,通信规则规定 ...

  9. html5文件夹上传下载组件

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...

  10. flask框架(八): 响应和请求

    from flask import Flask from flask import request from flask import render_template from flask impor ...