- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在考虑向 Oracle Bug 数据库提交 RFE(增强请求),这应该会显着提高字符串连接性能。但在我这样做之前,我想听听专家们对它是否有意义的评论。
这个想法是基于这样一个事实,即现有的 String.concat(String) 在 2 个字符串上的工作速度比 StringBuilder 快两倍。问题是没有连接 3 个或更多字符串的方法。外部方法无法做到这一点,因为 String.concat 使用包私有(private)构造函数 String(int offset, int count, char[] value)
,它不复制 char 数组而是直接使用它。这确保了 String.concat 的高性能。在同一个包中的 StringBuilder 仍然不能使用这个构造函数,因为那样的话 String 的 char 数组将被暴露以供修改。
我建议在String中添加以下方法
public static String concat(String s1, String s2)
public static String concat(String s1, String s2, String s3)
public static String concat(String s1, String s2, String s3, String s4)
public static String concat(String s1, String s2, String s3, String s4, String s5)
public static String concat(String s1, String... array)
注意:EnumSet.of 中使用了这种重载,以提高效率。
这是其中一种方法的实现,其他方法同理
public final class String {
private final char value[];
private final int count;
private final int offset;
String(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public static String concat(String s1, String s2, String s3) {
char buf[] = new char[s1.count + s2.count + s3.count];
System.arraycopy(s1.value, s1.offset, buf, 0, s1.count);
System.arraycopy(s2.value, s2.offset, buf, s1.count, s2.count);
System.arraycopy(s3.value, s3.offset, buf, s1.count + s2.count, s3.count);
return new String(0, buf.length, buf);
}
另外,将这些方法添加到String后,Java编译器会针对
String s = s1 + s2 + s3;
将能够高效地构建
String s = String.concat(s1, s2, s3);
代替现在的低效
String s = (new StringBuilder(String.valueOf(s1))).append(s2).append(s3).toString();
更新 性能测试。我在我的笔记本 Intel Celeron 925 上运行它,连接 3 个字符串,我的 String2 类完全模拟它在真实 java.lang.String 中的样子。选择字符串长度以便将 StringBuilder 置于最不利的条件下,即当它需要在每次追加时扩展其内部缓冲区容量时,而 concat 始终只创建一次 char[]。
public class String2 {
private final char value[];
private final int count;
private final int offset;
String2(String s) {
value = s.toCharArray();
offset = 0;
count = value.length;
}
String2(int offset, int count, char value[]) {
this.value = value;
this.offset = offset;
this.count = count;
}
public static String2 concat(String2 s1, String2 s2, String2 s3) {
char buf[] = new char[s1.count + s2.count + s3.count];
System.arraycopy(s1.value, s1.offset, buf, 0, s1.count);
System.arraycopy(s2.value, s2.offset, buf, s1.count, s2.count);
System.arraycopy(s3.value, s3.offset, buf, s1.count + s2.count, s3.count);
return new String2(0, buf.length, buf);
}
public static void main(String[] args) {
String s1 = "1";
String s2 = "11111111111111111";
String s3 = "11111111111111111111111111111111111111111";
String2 s21 = new String2(s1);
String2 s22 = new String2(s2);
String2 s23 = new String2(s3);
long t0 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
String2 s = String2.concat(s21, s22, s23);
// String s = new StringBuilder(s1).append(s2).append(s3).toString();
}
System.out.println(System.currentTimeMillis() - t0);
}
}
在 1,000,000 次迭代中,结果是:
version 1 = ~200 ms
version 2 = ~400 ms
最佳答案
事实是,单个字符串连接表达式的性能很重要的用例并不常见。在大多数情况下,性能受字符串连接的限制,它发生在一个循环中,逐步构建最终产品,在这种情况下,可变 StringBuilder
显然是赢家。这就是为什么我看不到通过干预基本的 String
类来优化少数关注的提案的前景。但无论如何,就比较性能而言,您的方法确实具有显着优势:
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;
public class Performance extends SimpleBenchmark
{
final Random rnd = new Random();
final String as1 = "aoeuaoeuaoeu", as2 = "snthsnthnsth", as3 = "3453409345";
final char[] c1 = as1.toCharArray(), c2 = as2.toCharArray(), c3 = as3.toCharArray();
public static char[] concat(char[] s1, char[] s2, char[] s3) {
char buf[] = new char[s1.length + s2.length + s3.length];
System.arraycopy(s1, 0, buf, 0, s1.length);
System.arraycopy(s2, 0, buf, s1.length, s2.length);
System.arraycopy(s3, 0, buf, s1.length + s2.length, s3.length);
return buf;
}
public static String build(String s1, String s2, String s3) {
final StringBuilder b = new StringBuilder(s1.length() + s2.length() + s3.length());
b.append(s1).append(s2).append(s3);
return b.toString();
}
public static String plus(String s1, String s2, String s3) {
return s1 + s2 + s3;
}
public int timeConcat(int reps) {
int tot = rnd.nextInt();
for (int i = 0; i < reps; i++) tot += concat(c1, c2, c3).length;
return tot;
}
public int timeBuild(int reps) {
int tot = rnd.nextInt();
for (int i = 0; i < reps; i++) tot += build(as1, as2, as3).length();
return tot;
}
public int timePlus(int reps) {
int tot = rnd.nextInt();
for (int i = 0; i < reps; i++) tot += plus(as1, as2, as3).length();
return tot;
}
public static void main(String... args) {
Runner.main(Performance.class, args);
}
}
结果:
0% Scenario{vm=java, trial=0, benchmark=Concat} 65.81 ns; σ=2.56 ns @ 10 trials
33% Scenario{vm=java, trial=0, benchmark=Build} 102.94 ns; σ=2.27 ns @ 10 trials
67% Scenario{vm=java, trial=0, benchmark=Plus} 160.14 ns; σ=2.94 ns @ 10 trials
benchmark ns linear runtime
Concat 65.8 ============
Build 102.9 ===================
Plus 160.1 ==============================
关于java - java.lang.String.concat 可以改进吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13778351/
我对编码还比较陌生,但并非完全没有经验。处理有关金融计算器的学校作业。如果你们中的任何人可以查看我的代码以了解不良做法/可能的改进等,那就太好了。 我确实添加了一个“动画”启动(有很多 printf
小目标Trick 论文链接: https://paperswithcode.com/paper/slicing-aided-hyper-inference-and-fine-tuning 代码链接:h
if (firstPositionCpc && (firstPosition > 0 && firstPositionCpc 0 && topOfPageCpc 0 && firstPageCpc
我有 2 个表:“packages”和“items”。 “packages”有以下列:pack_id | item_id “items”有以下列......:item_id |输入 一个包可以有多个
我目前有一个 Pandas Dataframe,我在其中执行列之间的比较。我发现一种情况,在进行比较时存在空列,由于某种原因比较返回 else 值。我添加了一个额外的语句来将其清理为空。看看我是否可以
我正在处理一个查询,通过首先舍入它们的主要日期时间键来连接一个数据库中的多个表。数据库包含来自 openhab 的性能数据,每个表只有一个名为 Time 的主日期时间行和一个名为 Value 的值行。
问候 我有一个程序创建一个类的多个实例,在所有实例上运行相同的长时间运行的 Update 方法并等待完成。我从 this question 开始关注 Kev 的方法将更新添加到 ThreadPool.
我想在下学期的类(class)中取得领先,所以我制作了这个基本版本的 Blackjack 来开始理解 C 的基础知识,我希望您有任何想法可以帮助我更好地理解 C 和其正常的编码实践。 C 中的很多东西
我有一个要求,比如: 给定一个数组,其中包含随机数。需要输出元素出现的次数,有自带解决方案: var myArr = [3,2,1,2,3,1,4,5,4,6,7,7,9,1,123,0,123];
这是我的数据库项目。 表user_ select id, name from user_; id | name ----+---------- 1 | bartek 2 | bartek
我已经完成了一个小批量脚本来调整(动态)一些图像的大小: for a in *.{png,PNG,jpg,JPG,jpeg,JPEG,bmp,BMP} ; do convert "$a" -resiz
是否有更 pythonic 的方法来执行以下代码?我想在一行中完成 parsed_rows 是一个可以返回大小为 3 或 None 的元组的函数。 parsed_rows = [ parse_row(
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improv
下面的代码完成了我想要的,但还有其他更像 python 风格的方式吗? 文件格式: key1:value1,key2:value2,... key21:value21,key22:value22,..
如果两个英文单词只包含相同的字母,则它们是相似的。例如,food 和 good 不相似,但 dog 和 good 相似。 (如果A与B相似,则A中的所有字母都包含在B中,B中的所有字母都包含在A中。)
我有以下结构来表示二叉树: typedef struct node *pnode; typedef struct node { int val; pnode left; pnode
我有一个区域,它由受约束的 delaunay 三角剖分表示。我正在解决在两点之间寻找路径的问题。我正在使用 Marcelo Kallmann 提供的论文作为解决此问题的引用点。然而,而不是使用 Kal
如果我需要检查文本(字符串)中是否存在单词 A 或单词 B,如果我这样做会有性能差异: if(text.contains(wordA) || text.contains(wordB)) 要使用一些正则
Adjust To 我有上面这个简单的页面,上面有一个标签和一个文本框。我想在文本框中输入文本。 对我有帮助的 XPATH 是 //*[contains(tex
以下伪代码的elisp代码 if "the emacs version is less than 23.1.x" do something else something-else 写成 (if
我是一名优秀的程序员,十分优秀!