[英]Is there a better way to traverse a string in java?
請多多包涵。 我沒有編程一年多了,目前我正在通過做“作業問題”來審查Java以進行面試。 我的函數應該返回一個字符串,其中包含給定字符串中的每個第二個字符。 有沒有那么尷尬的方法可以做到這一點?
public String stringBits(String str) {
StringBuffer tmp = new StringBuffer();
for(int i = 0; i<str.length(); i+=2)
tmp.append(str.charAt(i));
String ret = new String(tmp);
return ret;
我會使用StringBuilder
,而不是StringBuffer
。 StringBuffer
用於多線程情況,因此比StringBuilder
慢,因為它不同步。 我測試了該線程中各種答案列出的四種基本實現方法。 但是請注意,我總是在這里做某些事情。 這些應該是您的面試官真正想要的東西:
String += nextCharacter;
因為它比使用StringBuilder
慢得多,而且慢得多。 initialCapacity
是因為這樣做總是更快。 否則,如果StringBuilder
已滿,則必須重新分配一個新數組並復制過來,這很慢。 和代碼:
import com.google.caliper.Runner;
import com.google.caliper.SimpleBenchmark;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Random;
public class EveryOtherTest {
public static class StringBenchmark extends SimpleBenchmark {
private String input;
protected void setUp() {
Random r = new Random();
int length = r.nextInt(1000) + 1000;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append((char) ('A' + r.nextInt(26)));
}
input = sb.toString();
}
public String timeCharArrayForeach(int reps) {
String output = "";
Random r = new Random();
for (int i = 0; i < reps; i++) {
StringBuilder sb = new StringBuilder(input.length() / 2 + 1);
boolean use = false;
for (char c : input.toCharArray()) {
if(use) sb.append(c);
use = !use;
}
String newOutput = sb.toString();
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
public String timeCharArrayPlusTwo(int reps) {
String output = "";
Random r = new Random();
for (int i = 0; i < reps; i++) {
StringBuilder sb = new StringBuilder(input.length() / 2 + 1);
char[] charArray = input.toCharArray();
for(int j = 0; j < input.length(); j += 2) {
sb.append(charArray[j]);
}
String newOutput = sb.toString();
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
public String timeCharAt(int reps) {
String output = "";
Random r = new Random();
for (int i = 0; i < reps; i++) {
StringBuilder tmp = new StringBuilder(input.length() / 2 + 1);
for (int j = 0; j < input.length(); j += 2) {
tmp.append(input.charAt(j));
}
String newOutput = tmp.toString();
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
public String timeIterator(int reps) {
String output = "";
Random r = new Random();
for(int i = 0; i < reps; i++) {
StringBuilder buf = new StringBuilder(input.length() / 2 + 1);
StringCharacterIterator iterator = new StringCharacterIterator(input);
for (char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) {
buf.append(c);
iterator.next();
}
String newOutput = buf.toString();
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
public String timeRegex(int reps) {
String output = "";
Random r = new Random();
for(int i = 0; i < reps; i++) {
String newOutput = input.replaceAll("(?<!^).(.)", "$1");
if (r.nextBoolean()) output = newOutput; // Trick the JIT
}
return output;
}
}
public static void main(String... args) {
Runner.main(StringBenchmark.class, args);
}
}
結果:
0% Scenario{vm=java, trial=0, benchmark=CharArrayForeach} 2805.55 ns; ?=688.96 ns @ 10 trials
20% Scenario{vm=java, trial=0, benchmark=CharArrayPlusTwo} 3428.48 ns; ?=475.32 ns @ 10 trials
40% Scenario{vm=java, trial=0, benchmark=CharAt} 2138.68 ns; ?=379.44 ns @ 10 trials
60% Scenario{vm=java, trial=0, benchmark=Iterator} 3963.94 ns; ?=389.53 ns @ 10 trials
80% Scenario{vm=java, trial=0, benchmark=Regex} 58743.66 ns; ?=10850.33 ns @ 10 trials
benchmark us linear runtime
CharArrayForeach 2.81 =
CharArrayPlusTwo 3.43 =
CharAt 2.14 =
Iterator 3.96 ==
Regex 58.74 ==============================
vm: java
trial: 0
如果您喜歡迭代器方法,則有一個StringCharacterIterator類。
您可以使用此正則表達式等效項
String newString = str.replaceAll("(?<!^).(.)", "$1");
不。這一點都不尷尬。 對於每個有用的任務,可能會有更合適的方法,但是在這種情況下,您別無選擇,只能遍歷字符串。
我相信這也應該起作用,並且對我來說看起來更簡單。
public String stringBits(String str) {
String tmp = "";
for(int i = 0; i<str.length(); i+=2)
tmp+=str.charAt(i);
return tmp;
我編輯說,如果您想要第二,第四,六個...字符,我應該等於1。
您可以將字符串轉換為CharArray並使用for-each循環:
for (char c: str.toCharArray()){
}
當然,您可能需要一個計數器或一個標志才能獲取其他所有字符,因此它的位置可能不那么麻煩。
據我所知,你在做什么。 這是一個簡單的測試用例:
package com.sandbox;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class SandboxTest {
@Test
public void testMocking() {
assertEquals("foo", stringBits("f1o2o3"));
}
public String stringBits(String str) {
StringBuffer tmp = new StringBuffer();
for (int i = 0; i < str.length(); i += 2) {
tmp.append(str.charAt(i));
}
String ret = new String(tmp);
return ret;
}
}
我認為這是一種非常簡單的方法。 可以使用正則表達式和一組代碼來實現,但是我覺得您當前的代碼更容易閱讀。
在看到StringCharacterIterator
的答案之前,我從未聽說過StringCharacterIterator
,但這看起來是一個有趣的解決方案。 這是使用他的答案的代碼:
package com.sandbox;
import org.junit.Test;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import static org.junit.Assert.assertEquals;
public class SandboxTest {
@Test
public void testMocking() {
assertEquals("foo", stringBits("f1o2o3"));
}
public String stringBits(String str) {
StringBuilder buf = new StringBuilder();
StringCharacterIterator iterator = new StringCharacterIterator(str);
for (char c = iterator.first(); c != CharacterIterator.DONE; c = iterator.next()) {
buf.append(c);
iterator.next();
}
return buf.toString();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.