String.replace上的java.lang.OutOfMemoryError

Joe*_*mov 3 java android out-of-memory

我有一个文本文件,其中包含234行string1 @ string2 @ string3.

kya@??@??
kyu@??@??
kyo@??@??
sha@??@??
shu@??@??
...so 234 lines
Run Code Online (Sandbox Code Playgroud)

我正在编写转换器,将带有string2或string3的单词转换为带有string1的单词.

InputStream is = context.getResources().openRawResource(R.raw.kanatoromaji);
InputStreamReader isr = new InputStreamReader(is);
BufferedReader reader = new BufferedReader(isr);
String line;
try {
    while ((line = reader.readLine()) != null) {
        String[] parts = line.split("@");
        String romaji = parts[0];
        String hiragana=parts[1];
        String katakana = parts[2];

        if (hiragana!=null&&word.contains(hiragana)) {
                word = word.replace(hiragana, romaji);//in this line getting outOfMemory error
        }
        if (word.contains(katakana)) {
            word = word.replace(katakana, romaji);
        }
    }

} catch (IOException e) {
    e.printStackTrace();
}
Run Code Online (Sandbox Code Playgroud)

我多次调用这种方法(一次运行200k-300k次).所以这导致了这个错误:07-24 00:52:32.859 10848-10848/net.joerichard.test E/AndroidRuntime:FATAL

EXCEPTION: main
    java.lang.OutOfMemoryError
            at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:94)
            at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:132)
            at java.lang.StringBuilder.append(StringBuilder.java:124)
            at java.lang.String.replace(String.java:1367)
            at net.joerichard.test.Converter.kanaToRomaji(Converter.java:32)
            at net.joerichard.test.MainActivity.migrateKanaKanji(MainActivity.java:222)
            at net.joerichard.test.MainActivity.access$700(MainActivity.java:29)
            at net.joerichard.test.MainActivity$10.onClick(MainActivity.java:131)
            at android.view.View.performClick(View.java:4240)
            at android.view.View$PerformClick.run(View.java:17721)
            at android.os.Handler.handleCallback(Handler.java:730)
            at android.os.Handler.dispatchMessage(Handler.java:92)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5103)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

我的代码有什么问题?怎么解决?

更新:

根据JFPicard的回答,我将我的String字转换为StringBuilder sbWord.然后我尝试使用StringBuilder替换string2和string3.我之前从未替换过StringBuilder.我在谷歌搜索并找到了这个解决方案来替换我的StringBuilder部件.现在我的代码看起来像这样:

public static String kanaToRomaji(Context context, String word) {

    String kana = word;
    StringBuilder sbWord = new StringBuilder(word);

    InputStream is = context.getResources().openRawResource(R.raw.kanatoromaji);
    InputStreamReader isr = new InputStreamReader(is);
    BufferedReader reader = new BufferedReader(isr);
    String line;
    try {
        while ((line = reader.readLine()) != null) {
            String[] parts = line.split("@");
            String romaji = parts[0];
            String hiragana=parts[1];
            String katakana = parts[2];

            if (hiragana!=null&&word.contains(hiragana)) {
                sbWord = replaceAll(sbWord, hiragana, romaji);//in this line getting outOfMemory error
            }
            if (word.contains(katakana)) {
                sbWord = replaceAll(sbWord, katakana, romaji);
            }
        }

    }
    catch (IOException e) {
        e.printStackTrace();
    }

    char[] chars = kana.toCharArray();
    for (char character: chars)
    {
        if(sbWord.toString().contains(String.valueOf(character)))
        {
            new MyLog(kana+":"+sbWord.toString());
            break;
        }
    }

    return word;
}
Run Code Online (Sandbox Code Playgroud)

我替换我的StringBuilder部件的方法:

public static StringBuilder replaceAll(StringBuilder builder, String from, String to)
{
    int index = builder.indexOf(from);
    while (index != -1)
    {
        builder.replace(index, index + from.length(), to);
        index += to.length(); // Move to the end of the replacement
        index = builder.indexOf(from, index);
    }
    return builder;
}
Run Code Online (Sandbox Code Playgroud)

现在我收到此错误:07-24 01:23:52.890 13512-13512/net.joerichard.test E/AndroidRuntime:FATAL

EXCEPTION:java.lang.AbstractStringBuilder.inplace0上的java.lang.AbstractStringBuilder.insert0(AbstractStringBuilder.java:356)中的java.lang.AbstractStringBuilder.move(AbstractStringBuilder.java:397)中的主要java.lang.OutOfMemoryError(AbstractStringBuilder.java) :442)在java.lang.StringBuilder.replace(StringBuilder.java:637)at net.joerichard.test.Converter.replaceAll(Converter.java:65)at net.joerichard.test.Converter.kanaToRomaji(Converter.java: 33)net.joerichard.test.MainActivity.migrateKanaKanji(MainActivity.java:222)at net.joerichard.test.MainActivity.access $ 700(MainActivity.java:29)at net.joerichard.test.MainActivity $ 10.onClick(MainActivity) .java:131)在android.view.View.performClick(View.java:4240)在android.view.Handler.dispatchMessage(Handler.java:92)的android.view.View $ PerformClick.run(View.java:17721)android.os.Handler.handleCallback(Handler.java:730) android.os.Looper.loop(Looper.java:137)位于java.lang.reflect的java.lang.reflect.Method.invokeNative(Native Method)的android.app.ActivityThread.main(ActivityThread.java:5103).在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:737)上的Method.invoke(Method.java:525) at dalvik.system.NativeStart.main(Native Method)730)在android.os.Handler.dispatchMessage(Handler.java:92)的android.app.Looper.loop(Looper.java:137)在android.app.ActivityThread.main(ActivityThread.java:5103)的java处.位于com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:737)的java.lang.reflect.Method.invoke(Method.java:525)中的lang.reflect.Method.invokeNative(Native Method)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)at dalvik.system.NativeStart.main(Native Method)730)在android.os.Handler.dispatchMessage(Handler.java:92)的android.app.Looper.loop(Looper.java:137)在android.app.ActivityThread.main(ActivityThread.java:5103)的java处.位于com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:737)的java.lang.reflect.Method.invoke(Method.java:525)中的lang.reflect.Method.invokeNative(Native Method)at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)at dalvik.system.NativeStart.main(Native Method)在com.android.internal的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:737)的java.lang.reflect.Method.invoke(Method.java:525)中的invokeNative(Native Method). os.ZygoteInit.main(ZygoteInit.java:553)at dalvik.system.NativeStart.main(Native Method)在com.android.internal的com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:737)的java.lang.reflect.Method.invoke(Method.java:525)中的invokeNative(Native Method). os.ZygoteInit.main(ZygoteInit.java:553)at dalvik.system.NativeStart.main(Native Method)

在这种情况下该怎么办?

JFP*_*ard 6

我想我有个主意.

这条线 word = word.replace(hiragana, romaji);

还有这个 word = word.replace(katakana, romaji);

每次都创建一个新的String.String是不可变的,因此它消耗内存.在你的情况下很多.

尝试使用StringBuilder.