我正在阅读有关 Java 编译器如何在可能的情况下将与“+”运算符连接的字符串编译为 StringBuilder 实例的信息,以及这如何使使用简单的“+”运算符更好,因为它们 compile to the same code . (除非您在 while 循环中构建字符串,在这种情况下显然最好使用 StringBuilder。)
我还读到字符串上的 .concat 方法是最差的 choice all the time (以至于它被 Findbugs 变成了一个错误!)。
所以我决定自己在 eclipse 中编写一个小的 java 类来测试它。我的结果让我有点吃惊。我发现,如果我在 eclipse 中与在命令行中遵守并运行它们,则不同的方法相对更快或更慢。
首先我的 eclipse 结果是:
the total millis to concatenate with + was: 12154
the total millis to concatenate with .concat was: 8840
the total millis to concatenate with StringBuilder was: 11350
the total millis to concatenate with StringBuilder with a specified size was: 5611
因此在 eclipse 中,指定大小的 StringBuilder 最快,其次是 .concat(奇怪),然后 StringBuilder 和“+”连接几乎相同。
然而,我在命令行上的结果是:
the total millis to concatenate with + was: 4139
the total millis to concatenate with .concat was: 8590
the total millis to concatenate with StringBuilder was: 10888
the total millis to concatenate with StringBuilder with a specified size was: 6033
因此,当我从命令行编译和运行时,“+”运算符显然是最快的,其次是带大小的 String 构建器,然后是 concat,最后是普通的 StringBuilder!
这对我来说没有意义。显然,我读到的所有 stackoverflow 答案都说 + 运算符编译成普通的旧 StringBuilder 实例必须过时。
有人知道这里到底发生了什么吗?
我使用的是 jdk1.7.0_07,据我所知,eclipse 和我的命令行引用的是完全相同的一个。我知道的唯一区别是 eclipse 使用的是“javaw”,但从我读过的内容来看,这应该没有什么区别。
如果您想验证我没有做错任何事情,这是我的测试类,但我很确定它是可靠的。
public class Test {
static final int LOOPS = 100000000;
static final String FIRST_STRING = "This is such";
static final String SECOND_STRING = " an awesomely cool ";
static final String THIRD_STRING = "to write string.";
/**
* @param args
*/
public static void main(String[] args) {
Test.plusOperator();
Test.dotConcat();
Test.stringBuilder();
Test.stringBuilderSizeSpecified();
}
public static void plusOperator() {
String localOne = FIRST_STRING;
String localTwo = SECOND_STRING;
String localThree = THIRD_STRING;
Calendar startTime = Calendar.getInstance();
for (int x = 0; x < LOOPS; x++) {
String toPrint = localOne + localTwo + localThree;
}
Calendar endTime = Calendar.getInstance();
System.out.println("the total millis to concatenate with + was: " +
(endTime.getTimeInMillis() - startTime.getTimeInMillis()));
}
public static void stringBuilder() {
String localOne = FIRST_STRING;
String localTwo = SECOND_STRING;
String localThree = THIRD_STRING;
Calendar startTime = Calendar.getInstance();
for (int x = 0; x < LOOPS; x++) {
StringBuilder toBuild = new StringBuilder()
.append(localOne)
.append(localTwo)
.append(localThree);
}
Calendar endTime = Calendar.getInstance();
System.out.println("the total millis to concatenate with StringBuilder was: " +
(endTime.getTimeInMillis() - startTime.getTimeInMillis()));
}
public static void stringBuilderSizeSpecified() {
String localOne = FIRST_STRING;
String localTwo = SECOND_STRING;
String localThree = THIRD_STRING;
Calendar startTime = Calendar.getInstance();
for (int x = 0; x < LOOPS; x++) {
StringBuilder toBuild = new StringBuilder(50)
.append(localOne)
.append(localTwo)
.append(localThree);
}
Calendar endTime = Calendar.getInstance();
System.out.println("the total millis to concatenate with StringBuilder with a specified size was: " +
(endTime.getTimeInMillis() - startTime.getTimeInMillis()));
}
public static void dotConcat() {
String localOne = FIRST_STRING;
String localTwo = SECOND_STRING;
String localThree = THIRD_STRING;
Calendar startTime = Calendar.getInstance();
for (int x = 0; x < LOOPS; x++) {
String toPrint = localOne.concat(localTwo).concat(localThree);
}
Calendar endTime = Calendar.getInstance();
System.out.println("the total millis to concatenate with .concat was: " +
(endTime.getTimeInMillis() - startTime.getTimeInMillis()));
}
}
最佳答案
在 Oracle JDK 1.7 (javac 1.7.0_17) 上,“+”运算符仍然使用 StringBuilder 实现,如在类上运行 javap -c 所示获取字节码(这里只显示循环):
public static void plusOperator();
Code:
16: iload 4
18: ldc #10 // int 100000000
20: if_icmpge 53
23: new #11 // class java/lang/StringBuilder
26: dup
27: invokespecial #12 // Method java/lang/StringBuilder."<init>":()V
30: aload_0
31: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: aload_1
35: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
38: aload_2
39: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
42: invokevirtual #14 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
45: astore 5
47: iinc 4, 1
50: goto 16
public static void stringBuilder();
Code:
16: iload 4
18: ldc #10 // int 100000000
20: if_icmpge 50
23: new #11 // class java/lang/StringBuilder
26: dup
27: invokespecial #12 // Method java/lang/StringBuilder."<init>":()V
30: aload_0
31: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: aload_1
35: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
38: aload_2
39: invokevirtual #13 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
42: astore 5
44: iinc 4, 1
47: goto 16
这两者之间的唯一区别是带有“+”的版本在循环中将 StringBuilder 转换为 String。
所以问题就变成了:为什么您的测试对于相同的代码会显示如此不同的结果。或者更完整地说,为什么这不是一个有效的微基准测试。以下是一些可能的原因:
main()。关于java - StringBuilder vs.concat vs. "+"运算符在 eclipse 中的相对性能与命令行不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15397515/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
我想用ruby编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file