请耐心等待。我在一年多的时间里没有编程,而且我正在通过做“家庭作业问题”来审查我的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;
答案 0 :(得分:3)
我会使用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
答案 1 :(得分:2)
如果您更喜欢迭代器方法,则有一个StringCharacterIterator类。
答案 2 :(得分:1)
您可以使用此正则表达式等效
String newString = str.replaceAll("(?<!^).(.)", "$1");
答案 3 :(得分:0)
没有。这根本不尴尬。对于每个有用的任务,可能有更合适的方法,但在这种情况下,你别无选择,只能迭代字符串。
答案 4 :(得分:0)
我相信这也应该有效,对我来说看起来更简单。
public String stringBits(String str) {
String tmp = "";
for(int i = 0; i<str.length(); i+=2)
tmp+=str.charAt(i);
return tmp;
我编辑说如果你想要第二个,第四个,六个......字符,我应该等于1。
答案 5 :(得分:0)
您可以将字符串转换为CharArray并使用for-each循环:
for (char c: str.toCharArray()){
}
当然,你可能需要一个计数器或一个标志来获得其他所有角色,所以它可能不会那么尴尬。
答案 6 :(得分:0)
据我所知,你正在做什么。这是一个简单的测试用例:
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;
}
}
我认为这是一种非常直接的方式。使用正则表达式和组可能有一种方法,但我感觉您当前的代码更容易阅读。
在我看到@Joey的答案之前,我从未听说过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();
}
}