簡體   English   中英

有沒有更好的方法來遍歷java中的字符串?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM