1、startsWith(String prefix, int toffset)方法

包括startsWith(*),endsWith(*)方法,都是调用上述一个方法

     public boolean startsWith(String prefix, int toffset) {
char ta[] = value;
int to = toffset;
char pa[] = prefix.value;
int po = 0;
int pc = prefix.value.length;
// Note: toffset might be near -1>>>1.
if ((toffset < 0) || (toffset > value.length - pc)) {
return false;
}
while (--pc >= 0) {
if (ta[to++] != pa[po++]) {
return false;
}
}
return true;
}

上述算法的时间复杂度,最差的情况下为O(n)(取决于匹配子串的长度),最理想的情况下为O(1);

2、indexOf方法

有多个重载的方法,参数可以为字符,也可以为字符串

     static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
} char first = target[targetOffset];
int max = sourceOffset + (sourceCount - targetCount); for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
} /* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++); if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}

这个匹配子串的方法比较复杂,值得深入研究

3、substring方法

在JDK1.7之前的代码中,substring存在严重内存泄露问题,然而,这个问题在JDK1.7之后的版本中都有了改善;

因为JDK1.7中修改了构造方法,调用Arrays.copyOfRange()方法,只是复制出数组的一部分;

关于String类的构造方法,可以参看: JDK中String类的源码分析(一)

4、concat方法

连接两个字符串

     public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}

5、split方法,切割字符串

     public String[] split(String regex, int limit) {

         char ch = 0;
if (((regex.value.length == 1 &&
".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) ||
(regex.length() == 2 &&
regex.charAt(0) == '\\' &&
(((ch = regex.charAt(1))-'0')|('9'-ch)) < 0 &&
((ch-'a')|('z'-ch)) < 0 &&
((ch-'A')|('Z'-ch)) < 0)) &&
(ch < Character.MIN_HIGH_SURROGATE ||
ch > Character.MAX_LOW_SURROGATE))
{
int off = 0;
int next = 0;
boolean limited = limit > 0;
ArrayList<String> list = new ArrayList<>();
while ((next = indexOf(ch, off)) != -1) {
if (!limited || list.size() < limit - 1) {
list.add(substring(off, next));
off = next + 1;
} else { // last one
//assert (list.size() == limit - 1);
list.add(substring(off, value.length));
off = value.length;
break;
}
}
// If no match was found, return this
if (off == 0)
return new String[]{this}; // Add remaining segment
if (!limited || list.size() < limit)
list.add(substring(off, value.length)); // Construct result
int resultSize = list.size();
if (limit == 0)
while (resultSize > 0 && list.get(resultSize - 1).length() == 0)
resultSize--;
String[] result = new String[resultSize];
return list.subList(0, resultSize).toArray(result);
}
return Pattern.compile(regex).split(this, limit);
}

6、trim方法,去除字符串两端的空格

     public String trim() {
int len = value.length;
int st = 0;
char[] val = value; /* avoid getfield opcode */ while ((st < len) && (val[st] <= ' ')) {
st++;
}
while ((st < len) && (val[len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < value.length)) ? substring(st, len) : this;
}

算法时间复杂度在O(log(n))左右,截取,创建一个新的字符串;

总结:

在String类中的大多数方法,都存在new对象的操作,因为String的不可变性,如果大量的调用这些方法,在内存中会产生大量的String对象;

这样对GC的压力很非常大,很可能会出现内存溢出;

JDK中String类的源码分析(二)的更多相关文章

  1. JDK中String类的源码分析(一)

    1.String类是final的,不允许被继承 /** The value is used for character storage. */ private final char value[]; ...

  2. String类的源码分析

    之前面试的时候被问到有没有看过String类的源码,楼主当时就慌了,回来赶紧补一课. 1.构造器(构造方法) String类提供了很多不同的构造器,分别对应了不同的字符串初始化方法,此处从源码中摘录如 ...

  3. Netty中NioEventLoopGroup的创建源码分析

    NioEventLoopGroup的无参构造: public NioEventLoopGroup() { this(0); } 调用了单参的构造: public NioEventLoopGroup(i ...

  4. RocketMQ中Broker的启动源码分析(一)

    在RocketMQ中,使用BrokerStartup作为启动类,相较于NameServer的启动,Broker作为RocketMQ的核心可复杂得多 [RocketMQ中NameServer的启动源码分 ...

  5. RocketMQ中Broker的启动源码分析(二)

    接着上一篇博客  [RocketMQ中Broker的启动源码分析(一)] 在完成准备工作后,调用start方法: public static BrokerController start(Broker ...

  6. RocketMQ中Broker的消息存储源码分析

    Broker和前面分析过的NameServer类似,需要在Pipeline责任链上通过NettyServerHandler来处理消息 [RocketMQ中NameServer的启动源码分析] 实际上就 ...

  7. Springboot中mybatis执行逻辑源码分析

    Springboot中mybatis执行逻辑源码分析 在上一篇springboot整合mybatis源码分析已经讲了我们的Mapper接口,userMapper是通过MapperProxy实现的一个动 ...

  8. ABP源码分析二:ABP中配置的注册和初始化

    一般来说,ASP.NET Web应用程序的第一个执行的方法是Global.asax下定义的Start方法.执行这个方法前HttpApplication 实例必须存在,也就是说其构造函数的执行必然是完成 ...

  9. RocketMQ中PullConsumer的启动源码分析

    通过DefaultMQPullConsumer作为默认实现,这里的启动过程和Producer很相似,但相比复杂一些 [RocketMQ中Producer的启动源码分析] DefaultMQPullCo ...

随机推荐

  1. rebtree学习

    http://www.cnblogs.com/skywang12345/p/3245399.html http://www.cnblogs.com/skywang12345/p/3624177.htm ...

  2. import和from.…import…

    import和from.-import- 在讲之前我们先来讲一下怎样去下载第三方库,我们把python看作一部手机,pip就是应用管家,第三方库里面的模块就是应用管家里面的一个应用 一.import模 ...

  3. list 小练习

    li = ["alex", "WuSir", "ritian", "barry", "wenzhou" ...

  4. [..net core]4.入口,Main方法 及InProcess

    通常控件台程序都有一个main方法, public class Program { public static void Main(string[] args) { CreateWebHostBuil ...

  5. leetcode 75. Sort Colors (荷兰三色旗问题)

    Given an array with n objects colored red, white or blue, sort them in-place so that objects of the ...

  6. 实现 RSA 算法之 C 语言实现(第二章)(老物)

    第二章 如何实现应用RSA算法 趁着白天在自家店里的闲暇时间来写写第二章了,假设记住了第一章的各种定理之后,我们又该如何实现RSA密码的加密解密呢?也懒得废话了,直接进入正题吧. 先回顾几个知识点: ...

  7. QItemDelegate edit某个控件后把数据写回model

    QWidget *TrackDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const ...

  8. 深入理解Java的反射机制

    https://blog.csdn.net/u012585964/article/details/52011138 http://www.importnew.com/20339.html 一,java ...

  9. Python控制语句执行流程

    if语句: if<条件>:#条件之后必须有“:”.  <语句> if语句的三元运算符: <表达式1>if<条件>else<表达式2>:其语义 ...

  10. robotframework调用外部python多次运行拿到的都是同一个值

    外部python是一个爬虫,爬取的内容的定义没有放入函数中.导致一次爬取多次使用的情况出现. 第一版函数如下: 改版后: