这两种方法有哪些内存(或性能)问题?
What memory (or performance) issues does the two approaches have?
作为一名新手 Java
开发人员并且阅读了 String
class 并且对其功能仍然有些困惑。因此,我决定编写一种方法,将表单中的用户名大写,john 更改为 John 使用以下代码:
1st Approach
String firstUpper = username.substring(0, 1).toUpperCase();
String restLower = username.substring(1).toLowerCase();
return firstUpper.concat(restLower);
2nd Approach (method chaining)
return username.substring(0,1).toUpperCase().concat(username.substring(1).toLowerCase());
对性能或任何内存没有实际影响inflation。
在第一种方法中,您声明两个指向用户名字符串内容的变量,然后对字符串进行一些更改,创建两个新字符串,然后 return 将这两个新字符串连接起来产生第三个新字符串。
第二种方法你做同样的事情但是使用不可见的变量(在你子字符串之后你总是在堆中创建一个新的字符串)。 concat 操作也是如此。因此,就虚拟机和生成的代码而言,它们将执行相同的操作并且生成几乎相同的代码(在内存中创建字符串的位置)。
它们大多是等效的方法。但是如果你真的想要这个性能并且只需要第一个字母大写,那么
username.setCharAt(0, (Character.toUpperCase(username.charAt(0)));
您可以将此应用于字符串的其余部分,以使其他字符变为小写,例如
for (int i = 1; i < username.length(); i++)
username.setCharAt(i, (Character.toLowerCase(username.charAt(i)));
针对其他方法对这种方法进行压力测试可能有意义(通过调用它数千次以查看它的性能)。
编辑
字符串池节省了大量 space,代价是创建字符串的速度稍慢(以处理池)。
String pool helps in saving a lot of space for Java Runtime although
it takes more time to create the String.
When we use double quotes to create a String, it first looks for
String with the same value in the String pool, if found it just
returns the reference else it creates a new String in the pool and
then returns the reference.
However using new operator, we force String class to create a new
String object in heap space. We can use intern() method to put it into
the pool or refer to another String object from the string pool having
the same value.
来源:https://www.journaldev.com/797/what-is-java-string-pool
因此,如果您想将字符串池与不使用它进行比较,那么您需要创建并重新创建相同的字符串文字,并使用 new 运算符进行操作。在压力测试中,您可以比较它们的相对性能。如果我想做一个比较,我会先做这个测试:
for (int i = 0; i < 100000; i++) {
String foo = "abc";
}
对比
for (int i = 0; i < 100000; i++) {
String foo = new String("abc");
}
您实际上应该更喜欢使用 StringBuffer 或 StringBuilder 来处理此类事情。
然而,字符串池与您的两种方法都无关。
关于字符串池的典型问题如下所示:
String someString = new String("Shark");
How many strings will be created by the following code snippet? How many strings will exist in the string pool?
答案是 - 只会创建一个字符串,但会存在两个字符串。 "Shark"
String字面量在编译时会被放入String Pool中,构造函数调用会在运行时创建一个新的String对象,该对象不会在字符串池中,而是在堆中;并在满足正常条件时有资格进行垃圾回收。
如果我们在其上调用 .intern()
- new String("Shark").intern()
那么答案会变为 "only one string will be created, and only one string will exist. The .intern()
would return the reference to the "Shark" 来自字符串池,在编译时放置在那里,并且由 new String("Shark")
将被垃圾收集,因为不再有任何引用它。
字符串池问题的另一个例子是:
String s1 = "Shark";
String s2 = "Shark";
String s3 = new String("Shark");
String s4 = new String("Shark").intern();
System.out.println("s1 == s2 :"+(s1==s2));
System.out.println("s1 == s3 :"+(s1==s3));
System.out.println("s1 == s4 :"+(s1==s4));
What will be printed out by this code snippet?
这当然会打印出这个:
s1 == s2 :true
s1 == s3 :false
s1 == s4 :true
为了完整起见,上面的例子只会在字符串池中创建一个字符串,在堆中创建一个字符串。一个用于两个相同的 "Shark"
文字 - 在编译期间,一个在堆上用于 new String("Shark")
实例化,而 new String("Shark").intern()
将 return 引用 "Shark"
在编译时创建的文字。
EVERY 字符串文字将在字符串池中结束。但是您发布的问题与典型的字符串池问题没有任何关系。
作为一名新手 Java
开发人员并且阅读了 String
class 并且对其功能仍然有些困惑。因此,我决定编写一种方法,将表单中的用户名大写,john 更改为 John 使用以下代码:
1st Approach
String firstUpper = username.substring(0, 1).toUpperCase();
String restLower = username.substring(1).toLowerCase();
return firstUpper.concat(restLower);
2nd Approach (method chaining)
return username.substring(0,1).toUpperCase().concat(username.substring(1).toLowerCase());
对性能或任何内存没有实际影响inflation。
在第一种方法中,您声明两个指向用户名字符串内容的变量,然后对字符串进行一些更改,创建两个新字符串,然后 return 将这两个新字符串连接起来产生第三个新字符串。
第二种方法你做同样的事情但是使用不可见的变量(在你子字符串之后你总是在堆中创建一个新的字符串)。 concat 操作也是如此。因此,就虚拟机和生成的代码而言,它们将执行相同的操作并且生成几乎相同的代码(在内存中创建字符串的位置)。
它们大多是等效的方法。但是如果你真的想要这个性能并且只需要第一个字母大写,那么
username.setCharAt(0, (Character.toUpperCase(username.charAt(0)));
您可以将此应用于字符串的其余部分,以使其他字符变为小写,例如
for (int i = 1; i < username.length(); i++)
username.setCharAt(i, (Character.toLowerCase(username.charAt(i)));
针对其他方法对这种方法进行压力测试可能有意义(通过调用它数千次以查看它的性能)。
编辑
字符串池节省了大量 space,代价是创建字符串的速度稍慢(以处理池)。
String pool helps in saving a lot of space for Java Runtime although it takes more time to create the String.
When we use double quotes to create a String, it first looks for String with the same value in the String pool, if found it just returns the reference else it creates a new String in the pool and then returns the reference.
However using new operator, we force String class to create a new String object in heap space. We can use intern() method to put it into the pool or refer to another String object from the string pool having the same value.
来源:https://www.journaldev.com/797/what-is-java-string-pool
因此,如果您想将字符串池与不使用它进行比较,那么您需要创建并重新创建相同的字符串文字,并使用 new 运算符进行操作。在压力测试中,您可以比较它们的相对性能。如果我想做一个比较,我会先做这个测试:
for (int i = 0; i < 100000; i++) {
String foo = "abc";
}
对比
for (int i = 0; i < 100000; i++) {
String foo = new String("abc");
}
您实际上应该更喜欢使用 StringBuffer 或 StringBuilder 来处理此类事情。
然而,字符串池与您的两种方法都无关。
关于字符串池的典型问题如下所示:
String someString = new String("Shark");
How many strings will be created by the following code snippet? How many strings will exist in the string pool?
答案是 - 只会创建一个字符串,但会存在两个字符串。 "Shark"
String字面量在编译时会被放入String Pool中,构造函数调用会在运行时创建一个新的String对象,该对象不会在字符串池中,而是在堆中;并在满足正常条件时有资格进行垃圾回收。
如果我们在其上调用 .intern()
- new String("Shark").intern()
那么答案会变为 "only one string will be created, and only one string will exist. The .intern()
would return the reference to the "Shark" 来自字符串池,在编译时放置在那里,并且由 new String("Shark")
将被垃圾收集,因为不再有任何引用它。
字符串池问题的另一个例子是:
String s1 = "Shark";
String s2 = "Shark";
String s3 = new String("Shark");
String s4 = new String("Shark").intern();
System.out.println("s1 == s2 :"+(s1==s2));
System.out.println("s1 == s3 :"+(s1==s3));
System.out.println("s1 == s4 :"+(s1==s4));
What will be printed out by this code snippet?
这当然会打印出这个:
s1 == s2 :true
s1 == s3 :false
s1 == s4 :true
为了完整起见,上面的例子只会在字符串池中创建一个字符串,在堆中创建一个字符串。一个用于两个相同的 "Shark"
文字 - 在编译期间,一个在堆上用于 new String("Shark")
实例化,而 new String("Shark").intern()
将 return 引用 "Shark"
在编译时创建的文字。
EVERY 字符串文字将在字符串池中结束。但是您发布的问题与典型的字符串池问题没有任何关系。