一看指令码,这不是在循环里(if_icmpgt)给我 new 了 StringBuilder 了吗,怎么还这么慢呢?再仔细看,其实你会发现,这new是在循环里吗呀,我们把这段代码写出来再看看;
String str = ""; for (int i = 0; i < 10000; i++) { str = new StringBuilder().append(str).append(i).toString(); }
现在再看这段代码就很清晰了,所有的字符串链接操作,都需要实例化一次StringBuilder,所以非常耗时。「并且你可以验证,这样写代码耗时与字符串直接链接是一样的。」 所以把StringBuilder 提到上一层 for 循环外更快。
四、String 源码分析
publicfinalclassString implementsjava.io.Serializable, Comparable<String>, CharSequence{ /** The value is used for character storage. */ privatefinalchar value[];
/** Cache the hash code for the string */ privateint hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */ privatestaticfinallong serialVersionUID = -6849794470754667710L;
/** * Returns a canonical representation for the string object. * <p> * A pool of strings, initially empty, is maintained privately by the * class {@code String}. * <p> * When the intern method is invoked, if the pool already contains a * string equal to this {@code String} object as determined by * the {@link #equals(Object)} method, then the string from the pool is * returned. Otherwise, this {@code String} object is added to the * pool and a reference to this {@code String} object is returned. * <p> * It follows that for any two strings {@code s} and {@code t}, * {@code s.intern() == t.intern()} is {@code true} * if and only if {@code s.equals(t)} is {@code true}. * <p> * All literal strings and string-valued constant expressions are * interned. String literals are defined in section 3.10.5 of the * <cite>The Java™ Language Specification</cite>. * * @return a string that has the same contents as this string, but is * guaranteed to be from a pool of unique strings. */ publicnative String intern();
public AbstractStringBuilder append(String str){ if (str == null) return appendNull(); int len = str.length(); ensureCapacityInternal(count + len); str.getChars(0, len, value, count); count += len; returnthis; }
这个是 public final class StringBuilder extends AbstractStringBuilder,的父类与 StringBuffer 共用这个方法。
这里包括了容量检测、元素拷贝、记录 count 数量。
2.2 扩容操作
「ensureCapacityInternal(count + len);」
/** * This method has the same contract as ensureCapacity, but is * never synchronized. */ privatevoidensureCapacityInternal(int minimumCapacity){ // overflow-conscious code if (minimumCapacity - value.length > 0) expandCapacity(minimumCapacity); }
/** * This implements the expansion semantics of ensureCapacity with no * size check or synchronization. */ voidexpandCapacity(int minimumCapacity){ int newCapacity = value.length * 2 + 2; if (newCapacity - minimumCapacity < 0) newCapacity = minimumCapacity; if (newCapacity < 0) { if (minimumCapacity < 0) // overflow thrownew OutOfMemoryError(); newCapacity = Integer.MAX_VALUE; } value = Arrays.copyOf(value, newCapacity); }
如上,StringBuilder,就跟操作数组的原理一样,都需要检测容量大小,按需扩容。扩容的容量是 n * 2 + 2,另外把原有元素拷贝到新新数组中。
2.3 填充元素
「str.getChars(0, len, value, count);」
publicvoidgetChars(int srcBegin, int srcEnd, char dst[], int dstBegin){ // ... System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); }
添加元素的方式是基于 System.arraycopy 拷贝操作进行的,这是一个本地方法。
2.4 toString()
既然 stringBuilder 是数组,那么它是怎么转换成字符串的呢?
stringBuilder.toString();
@Override public String toString(){ // Create a copy, don't share the array returnnew String(value, 0, count); }
Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。
Rocky Linux
Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。