我想遍历String中的每个字符,并将String的每个字符作为String传递给另一个函数。
String s = "abcdefg";
for(int i = 0; i < s.length(); i++){
newFunction(s.substring(i, i+1));}
或
String s = "abcdefg";
for(int i = 0; i < s.length(); i++){
newFunction(Character.toString(s.charAt(i)));}
最终结果必须是String。那么任何更快或更有效的想法呢?
答案 0 :(得分:15)
答案是:it doesn't matter。
描述您的代码。这是你的瓶颈吗?
答案 1 :(得分:15)
像往常一样:没关系,但如果你坚持花时间进行微优化,或者你真的想优化你的特殊用例,试试这个:
import org.junit.Assert;
import org.junit.Test;
public class StringCharTest {
// Times:
// 1. Initialization of "s" outside the loop
// 2. Init of "s" inside the loop
// 3. newFunction() actually checks the string length,
// so the function will not be optimized away by the hotstop compiler
@Test
// Fastest: 237ms / 562ms / 2434ms
public void testCacheStrings() throws Exception {
// Cache all possible Char strings
String[] char2string = new String[Character.MAX_VALUE];
for (char i = Character.MIN_VALUE; i < Character.MAX_VALUE; i++) {
char2string[i] = Character.toString(i);
}
for (int x = 0; x < 10000000; x++) {
char[] s = "abcdefg".toCharArray();
for (int i = 0; i < s.length; i++) {
newFunction(char2string[s[i]]);
}
}
}
@Test
// Fast: 1687ms / 1725ms / 3382ms
public void testCharToString() throws Exception {
for (int x = 0; x < 10000000; x++) {
String s = "abcdefg";
for (int i = 0; i < s.length(); i++) {
// Fast: Creates new String objects, but does not copy an array
newFunction(Character.toString(s.charAt(i)));
}
}
}
@Test
// Very fast: 1331 ms/ 1414ms / 3190ms
public void testSubstring() throws Exception {
for (int x = 0; x < 10000000; x++) {
String s = "abcdefg";
for (int i = 0; i < s.length(); i++) {
// The fastest! Reuses the internal char array
newFunction(s.substring(i, i + 1));
}
}
}
@Test
// Slowest: 2525ms / 2961ms / 4703ms
public void testNewString() throws Exception {
char[] value = new char[1];
for (int x = 0; x < 10000000; x++) {
char[] s = "abcdefg".toCharArray();
for (int i = 0; i < s.length; i++) {
value[0] = s[i];
// Slow! Copies the array
newFunction(new String(value));
}
}
}
private void newFunction(String string) {
// Do something with the one-character string
Assert.assertEquals(1, string.length());
}
}
答案 2 :(得分:4)
newFunction
真的需要String
吗?如果你能newFunction
取char
并将其称为这样,那会更好:
newFunction(s.charAt(i));
这样,您就可以避免创建临时String对象。
回答你的问题:很难说哪一个更有效率。在这两个示例中,都必须创建一个只包含一个字符的String
对象。哪个更有效取决于在特定Java实现上实现String.substring(...)
和Character.toString(...)
的准确程度。找到它的唯一方法是通过分析器运行程序,并查看哪个版本使用更多CPU和/或更多内存。通常情况下,您不应该担心像这样的微优化 - 只有在您发现这是性能和/或内存问题的原因时才花时间。
答案 3 :(得分:2)
在你发布的两个片段中,我不想说。我同意Will的观点,它几乎肯定与代码的整体性能无关 - 如果不是,你可以自己做出改变,并自己确定哪些对你的硬件上的JVM最快的数据。
也就是说,如果先将String转换为char数组,然后在数组上执行迭代,那么第二个代码段可能会更好。这样做只会执行一次String开销(转换为数组)而不是每次调用。此外,您可以使用一些索引将数组直接传递给String构造函数,这比使用数组的char out 单独传递它更有效(然后将其转换为单字符数组):
String s = "abcdefg";
char[] chars = s.toCharArray();
for(int i = 0; i < chars.length; i++) {
newFunction(String.valueOf(chars, i, 1));
}
但是为了强调我的第一点,当你在String.charAt()
的每次调用中查看你实际上避免的内容时 - 它是两个边界检查,一个(懒惰)布尔OR和一个加法。这不会产生任何明显的差异。字符串构造函数也不同。
基本上,这两个成语在性能方面都很好(两者都没有立即显然效率低下),所以你不应该花费更多的时间来处理它们,除非探查器显示这会占用你应用程序的大量运行时间。即便如此,通过在此区域重组支持代码,您几乎可以肯定地获得更多性能提升(例如,让newFunction
获取整个字符串本身);到目前为止,java.lang.String得到了很好的优化。
答案 4 :(得分:0)
我首先使用String.toCharArray()从源String获取底层char [],然后继续调用newFunction。
但我同意Jesper的意见,如果你能处理字符并避免所有字符串函数,那将是最好的......
答案 5 :(得分:0)
Leetcode似乎更喜欢子字符串选项here。
这就是我解决该问题的方法:
class Solution {
public int strStr(String haystack, String needle) {
if(needle.length() == 0) {
return 0;
}
if(haystack.length() == 0) {
return -1;
}
for(int i=0; i<=haystack.length()-needle.length(); i++) {
int count = 0;
for(int j=0; j<needle.length(); j++) {
if(haystack.charAt(i+j) == needle.charAt(j)) {
count++;
}
}
if(count == needle.length()) {
return i;
}
}
return -1;
}
}
这是他们提供的最佳解决方案:
class Solution {
public int strStr(String haystack, String needle) {
int length;
int n=needle.length();
int h=haystack.length();
if(n==0)
return 0;
// if(n==h)
// length = h;
// else
length = h-n;
if(h==n && haystack.charAt(0)!=needle.charAt(0))
return -1;
for(int i=0; i<=length; i++){
if(haystack.substring(i, i+needle.length()).equals(needle))
return i;
}
return -1;
}
}
老实说,我不知道为什么会这么重要。