使用pinyin4j实现自动完成的功能,汉字中有好多多音字,所以用的是二维数组去接pinyin4j转出来的音调。然后对该二维数组进行全排列,获取到所有拼接好的拼音字符串并返回。全排列时使用的是递归,但是最近发现了自动完成会导致内存溢出,查了原因发现,如果数据库中的数据过多,在调用全排列的递归时,会导致内存溢出的。想了很多办法,都快急死了现在不知道该如何解决。如果有此经验的大侠们,赶快帮帮小弟,不胜感激。我先把我递归的代码发出来,看看能优化不:
    /**
     * 递归
     * @param strJaggedArray 需要递归的二维数组
     * @return 最终返回的字符串数组
     */
    private static String[][] DoExchange(String[][] strJaggedArray)
    {
        int len = strJaggedArray.length;
        String[][] newArray = null;
        String[] temp = null;
        int Index = 0;
        int newlen = 0;
        //如果返回的拼音数组长度大于1(多音字),进行递归
        if (len > 1)
        {
            int len1 = 0;
            int len2 = 0;
            if(null != strJaggedArray[0])
            {
                len1 = strJaggedArray[0].length;
            } else {
             len1 = 1;
            }
            
            
            if(null != strJaggedArray[1])
            {
                len2 = strJaggedArray[1].length;
            } else {
             len2 = 1;
            }            //计算目标二维数组长度(即全排列之后的长度)
            newlen = len1 * len2;
            temp = new String[newlen];
            //开始对多个拼音进行拼接
            for (int i = 0; i < len1; i++)
            {
                for (int j = 0; j < len2; j++)
                {
                 if (null != strJaggedArray[0] && null != strJaggedArray[1]) {
                 //第一次进入该递归时默认拼接数组的前两个元素,从第二次开始,拼装第1个和第3个,第三次是第1个和第4个,以此类推
                 temp[Index] = strJaggedArray[0][i] + strJaggedArray[1][j];
                 Index++;
                 } else if (null != strJaggedArray[0] && null == strJaggedArray[1]) {
                 temp[Index] = strJaggedArray[0][i];
                 Index++;
                 } else if (null == strJaggedArray[0] && null != strJaggedArray[1]) {
                 temp[Index] = strJaggedArray[1][j];
                 Index++;
                 }
                }
            }
            //需要递归的数组都会比传入的数组长度小1
            newArray = new String[len - 1][];
            //从2开始循环,是需要将newArray[0]留出来存放我们最终需要的拼接好的字符串使用
            for (int i = 2; i < len; i++)
            {
                newArray[i - 1] = strJaggedArray[i];
            }
            //这里其实是将传进来需要处理的数组第一个元素修改为我们需要的字符串。也就是说,每一次递归,都是修改原数组的第一个元素。(注意,问题就出在这里,因为每次都要把拼接好的字符串放到数组第一位,所以当字符串很长时,就会造成内存溢出。)
            newArray[0] = temp;

            System.out.println(newArray[0][0]);
            System.out.println(newArray[0].length);
            //继续递归
            return DoExchange(newArray);
        }
        else
        {
            //如果递归到某一步传入的数组长度小于2,直接返回该数组
            return strJaggedArray;
        }
    }

解决方案 »

  1.   

    如果数据量大,就把JVM内存调大点吧。
    如果数据量太大了,就不要把所有数据都一次性放到数组里。往往也不需要这样做。
      

  2.   

    原来有pinyin4J这东东的。学习学习。
      

  3.   


    /**
     * 递归
     * 
     * @param strJaggedArray
     *            需要递归的二维数组
     * @return 最终返回的字符串数组
     */
    private static String[][] DoExchange(String[][] strJaggedArray) {
    // 如果返回的拼音数组长度大于1(多音字),进行递归
    while (strJaggedArray.length > 1) {
    String[][] newArray = null;
    String[] temp = null;
    int Index = 0;
    int newlen = 0;
    int len1 = 0;
    int len2 = 0;
    if (null != strJaggedArray[0]) {
    len1 = strJaggedArray[0].length;
    } else {
    len1 = 1;
    } if (null != strJaggedArray[1]) {
    len2 = strJaggedArray[1].length;
    } else {
    len2 = 1;
    } // 计算目标二维数组长度(即全排列之后的长度)
    newlen = len1 * len2;
    temp = new String[newlen];
    // 开始对多个拼音进行拼接
    for (int i = 0; i < len1; i++) {
    for (int j = 0; j < len2; j++) {
    if (null != strJaggedArray[0] && null != strJaggedArray[1]) {
    // 第一次进入该递归时默认拼接数组的前两个元素,从第二次开始,拼装第1个和第3个,第三次是第1个和第4个,以此类推
    temp[Index] = strJaggedArray[0][i]
    + strJaggedArray[1][j];
    Index++;
    } else if (null != strJaggedArray[0]
    && null == strJaggedArray[1]) {
    temp[Index] = strJaggedArray[0][i];
    Index++;
    } else if (null == strJaggedArray[0]
    && null != strJaggedArray[1]) {
    temp[Index] = strJaggedArray[1][j];
    Index++;
    }
    }
    }
    // 需要递归的数组都会比传入的数组长度小1
    newArray = new String[strJaggedArray.length - 1][];
    // 从2开始循环,是需要将newArray[0]留出来存放我们最终需要的拼接好的字符串使用
    for (int i = 2; i < strJaggedArray.length; i++) {
    newArray[i - 1] = strJaggedArray[i];
    }
    // 这里其实是将传进来需要处理的数组第一个元素修改为我们需要的字符串。也就是说,每一次递归,都是修改原数组的第一个元素。[color=#FF0000](注意,问题就出在这里,因为每次都要把拼接好的字符串放到数组第一位,所以当字符串很长时,就会造成内存溢出。)
    newArray[0] = temp;
    System.out.println(newArray[0][0]);
    System.out.println(newArray[0].length);
    // 继续递归
    strJaggedArray = newArray;
    }
    // 如果递归到某一步传入的数组长度小于2,直接返回该数组
    return strJaggedArray;
    }这样试试?
      

  4.   

    下面是我用System.nanoTime()测试出的结果:
    IDo
    18
    ==========经过优化的
    443073
    [[IDo, Iyou, Ilove, Ime, Iguys, I?, loveDo, loveyou, lovelove, loveme, loveguys, love?, youDo, youyou, youlove, youme, youguys, you?]]
    IDo
    18
    [[IDo, Iyou, Ilove, Ime, Iguys, I?, loveDo, loveyou, lovelove, loveme, loveguys, love?, youDo, youyou, youlove, youme, youguys, you?]]
    未经过优化的==12061825829819
    效果太明显了,lz请看
      

  5.   

    擦,不好意思,前面弄了点错误,终于大功告成,看看效果:package net.liuyx.test;import java.util.Arrays;public class Test333 {
    public static void main(String[] args) {
    String[][] a = {
    {"I","love","you"},{"Do","you","love","me","guys","?"}
    };
    String[][] re = DoExchange(a);
    System.out.println(Arrays.deepToString(re));

    long start = System.nanoTime();
    String[][] re2 = DoExchange2(a);
    System.out.println(Arrays.deepToString(re2));
    long duration = System.nanoTime()-start;
    System.out.println("未经过优化的==" + duration);

    }
    /**
     * 递归
     * 
     * @param handle
     *            需要递归的二维数组
     * @return 最终返回的字符串数组
     */
    private static String[][] DoExchange(String[][] strJaggedArray) {
    long start = System.nanoTime();
    // 如果返回的拼音数组长度大于1(多音字),进行递归
    while (true) {
    if(strJaggedArray.length > 1)
    break;
    String[][] newArray = null;
    String[] temp = null;
    int Index = 0;
    int newlen = 0;
    int len1 = 0;
    int len2 = 0;
    if (null != strJaggedArray[0]) {
    len1 = strJaggedArray[0].length;
    } else {
    len1 = 1;
    } if (null != strJaggedArray[1]) {
    len2 = strJaggedArray[1].length;
    } else {
    len2 = 1;
    } // 计算目标二维数组长度(即全排列之后的长度)
    newlen = len1 * len2;
    temp = new String[newlen];
    // 开始对多个拼音进行拼接
    for (int i = 0; i < len1; i++) {
    for (int j = 0; j < len2; j++) {
    if (null != strJaggedArray[0] && null != strJaggedArray[1]) {
    // 第一次进入该递归时默认拼接数组的前两个元素,从第二次开始,拼装第1个和第3个,第三次是第1个和第4个,以此类推
    temp[Index] = strJaggedArray[0][i]
    + strJaggedArray[1][j];
    Index++;
    } else if (null != strJaggedArray[0]
    && null == strJaggedArray[1]) {
    temp[Index] = strJaggedArray[0][i];
    Index++;
    } else if (null == strJaggedArray[0]
    && null != strJaggedArray[1]) {
    temp[Index] = strJaggedArray[1][j];
    Index++;
    }
    }
    }
    // 需要递归的数组都会比传入的数组长度小1
    newArray = new String[strJaggedArray.length - 1][];
    // 从2开始循环,是需要将newArray[0]留出来存放我们最终需要的拼接好的字符串使用
    for (int i = 2; i < strJaggedArray.length; i++) {
    newArray[i - 1] = strJaggedArray[i];
    }
    // 这里其实是将传进来需要处理的数组第一个元素修改为我们需要的字符串。也就是说,每一次递归,都是修改原数组的第一个元素。[color=#FF0000](注意,问题就出在这里,因为每次都要把拼接好的字符串放到数组第一位,所以当字符串很长时,就会造成内存溢出。)
    newArray[0] = temp;
    System.out.println(newArray[0][0]);
    System.out.println(newArray[0].length);
    // 继续递归
    strJaggedArray = newArray;
    }
    long duration = System.nanoTime() - start;
    System.out.println("经过优化的==" + duration);
    // 如果递归到某一步传入的数组长度小于2,直接返回该数组
    return strJaggedArray;
    }
    /**
         * 递归
         * @param strJaggedArray 需要递归的二维数组
         * @return 最终返回的字符串数组
         */
        private static String[][] DoExchange2(String[][] strJaggedArray)
        {
            int len = strJaggedArray.length;
            String[][] newArray = null;
            String[] temp = null;
            int Index = 0;
            int newlen = 0;
            //如果返回的拼音数组长度大于1(多音字),进行递归
            if (len > 1)
            {
                int len1 = 0;
                int len2 = 0;
                if(null != strJaggedArray[0])
                {
                    len1 = strJaggedArray[0].length;
                } else {
                    len1 = 1;
                }
                
                
                if(null != strJaggedArray[1])
                {
                    len2 = strJaggedArray[1].length;
                } else {
                    len2 = 1;
                }            //计算目标二维数组长度(即全排列之后的长度)
                newlen = len1 * len2;
                temp = new String[newlen];
                //开始对多个拼音进行拼接
                for (int i = 0; i < len1; i++)
                {
                    for (int j = 0; j < len2; j++)
                    {
                        if (null != strJaggedArray[0] && null != strJaggedArray[1]) {
                            //第一次进入该递归时默认拼接数组的前两个元素,从第二次开始,拼装第1个和第3个,第三次是第1个和第4个,以此类推
                            temp[Index] = strJaggedArray[0][i] + strJaggedArray[1][j];
                            Index++;
                        } else if (null != strJaggedArray[0] && null == strJaggedArray[1]) {
                            temp[Index] = strJaggedArray[0][i];
                            Index++;
                        } else if (null == strJaggedArray[0] && null != strJaggedArray[1]) {
                            temp[Index] = strJaggedArray[1][j];
                            Index++;
                        }
                    }
                }
                //需要递归的数组都会比传入的数组长度小1
                newArray = new String[len - 1][];
                //从2开始循环,是需要将newArray[0]留出来存放我们最终需要的拼接好的字符串使用
                for (int i = 2; i < len; i++)
                {
                    newArray[i - 1] = strJaggedArray[i];
                }
                //这里其实是将传进来需要处理的数组第一个元素修改为我们需要的字符串。也就是说,每一次递归,都是修改原数组的第一个元素。[color=#FF0000](注意,问题就出在这里,因为每次都要把拼接好的字符串放到数组第一位,所以当字符串很长时,就会造成内存溢出。)
                newArray[0] = temp;
                System.out.println(newArray[0][0]);
                System.out.println(newArray[0].length);
                //继续递归
                return DoExchange2(newArray);
            }
            else
            {
                //如果递归到某一步传入的数组长度小于2,直接返回该数组
                return strJaggedArray;
            }
        }}
    最后程序输出:
    经过优化的==1956
    [[I, love, you], [Do, you, love, me, guys, ?]]
    IDo
    18
    [[IDo, Iyou, Ilove, Ime, Iguys, I?, loveDo, loveyou, lovelove, loveme, loveguys, love?, youDo, youyou, youlove, youme, youguys, you?]]
    未经过优化的==310095
    这回没错了,lz给分哈哈哈
      

  6.   


    额。。这还需要我给你啊,自己写一个main方法去调用么