【问题标题】:How to make for() loop take less time (android)?如何使 for() 循环花费更少的时间(android)?
【发布时间】:2013-03-05 11:37:19
【问题描述】:

我正在为 Android 设备制作应用程序。我的应用程序中有一个函数,它有 2 个“for 循环”,每个循环 3200 次,访问一个 53 KB 的 .txt 文件(包含 3200 行)并将字符串与每一行进行比较,每次迭代一行。 “for 循环”还包含 BufferedReader()、InputStreamReader()、InputStream() 和 StringTokenizer()。因此,当我在模拟器上运行应用程序时,它处理该功能大约需要 8 秒。这是不可接受的。如何将所需的时间减少到半秒或最多。 1秒?谢谢! 编辑:这是我的程序的一部分,带有 2 个 for 循环:

else if(a==2){
        String z="";
        try{
            InputStream is = getAssets().open("USCOUNTIES.txt");
            InputStreamReader iz=new InputStreamReader(is);
            BufferedReader bis = new BufferedReader(iz);

            int v=0;

            v=count("USCOUNTIES.txt");//counts number of lines in the .txt file
        //finding no. of counties to be displayed
            int counter=0;
            String pos;
            pos=Integer.toString(position);
            try{
            for(int i=0;i<v;i++){
                z=bis.readLine();
                //int x=pos.length();
                boolean a;
                //using stringtokenizer
                StringTokenizer st = new StringTokenizer(z, ","); 
                String substring;
                substring=(String) st.nextElement();
                a=substring.equals(pos);
                if(a==true){

                    counter=counter+1;

                }
            }}catch(Exception e){e.printStackTrace();}
            String array1[]=new String[counter];

            try{
                InputStream ig = getAssets().open("USCOUNTIES.txt");
                InputStreamReader ia=new InputStreamReader(ig);
                BufferedReader bos = new BufferedReader(ia);
            int j=0;
            for(int i=0;i<v;i++){
                z=bos.readLine();
                String[] split = z.split(",");
                if(split[0].equals(pos)){
                    array1[j]=split[1];
                    j=j+1;
                }

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

【问题讨论】:

  • 老实说,8秒读取3200个文件,每行3200行已经很不错了。
  • 它是一个单行 3200 行的文件。并且迭代了 3200 次。你可能有什么建议?我这样做是为了将文件的一些数据放在一个列表中。
  • 你为什么要重读同一个文件3200次
  • 嗯,如果是单个文件,为什么要加载 3200 次?只需在循环外加载一次
  • 你的文件结构是什么?看到您在文件中迭代完全相同数量的行,我怀疑您可以只迭代一次并将所有内容解析为 Map。

标签: android optimization iteration


【解决方案1】:

如果我是你,我会只解析一次所有内容,然后随心所欲地处理它。

这段代码就是这样做的,包括解析Integers(我怀疑你需要这些作为值,而不是Strings):

public void read() throws IOException {
    InputStream is = getAssets().open("USCOUNTIES.txt");
    InputStreamReader iz=new InputStreamReader(is);
    BufferedReader bis = new BufferedReader(iz);
    String line = "";
    String firstNumber = "";
    String secondNumber = "";
    String countyName = "";
    StringTokenizer st = null;
    HashMap<Pair, String> map = new HashMap<>();
    while((line = bis.readLine()) != null) {
        st = new StringTokenizer(line, ",");
        firstNumber = (String) st.nextElement();
        st = new StringTokenizer((String)st.nextElement(), ">");
        secondNumber = (String) st.nextElement();
        countyName = ((String) st.nextElement());
        countyName = countyName.substring(0, countyName.length()-1);
        int num1 = Integer.parseInt(firstNumber);
        int num2 = Integer.parseInt(secondNumber);
        map.put(new Pair(num1, num2), countyName);
    }
}

class Pair {
    int num1, num2;
    Pair(int num1, int num2) {
        this.num1 = num1;
        this.num2 = num2;
    }

    public boolean equals(Object other) {
        if (other instanceof Pair) {
            Pair np = (Pair) other;
            return this.num1 == np.num1 && this.num2 == np.num2;
        }
        return false;
    }

    public int hashCode() {
        return (Integer.valueOf(num1).hashCode() >> 13) ^ Integer.valueOf(num2).hashCode();
    };
}

现在您可以使用此行简单地检索每个 countyName

String s = map.get(new Pair(1,69));

然后返回Aleutians East

我希望这能让你开始。

编辑

这段代码使用二维的SparseArray(很像HashMap&lt;Integer, Object&gt;)。这样,所有内容都按第一个数字排序。

public class Reader {
    private String firstNumber = "";
    private String secondNumber = "";
    private String countyName = "";
    private StringTokenizer stringTokenizer = null;
    private SparseArray<SparseArray<String>> sparseArray = new SparseArray<SparseArray<String>>();
    private SparseArray<String> temporarySparseArray = null;

    public void readFromIS() throws IOException {
        InputStream is = getAssets().open("USCOUNTIES.txt");
        InputStreamReader iz=new InputStreamReader(is);
        BufferedReader bis = new BufferedReader(iz);
        String line = null;
        while((line = bis.readLine()) != null) {
            readLine(line);
        }
    }

    public void readFromList() {
        String[] strings = {
                "0,1>Autauga;",
                "0,2>Baldwin;",
                "0,3>Barbour;",
                "1,69>Aleutians East;",     
                "1,68>Aleutians West;"
        };
        for (String line : strings) {
            readLine(line);
        }
    }

    private void readLine(String line) {
        stringTokenizer = new StringTokenizer(line, ",");
        firstNumber = (String) stringTokenizer.nextElement();
        stringTokenizer = new StringTokenizer((String)stringTokenizer.nextElement(), ">");
        secondNumber = (String) stringTokenizer.nextElement();
        countyName = ((String) stringTokenizer.nextElement());
        countyName = countyName.substring(0, countyName.length()-1);
        int num1 = Integer.parseInt(firstNumber);
        int num2 = Integer.parseInt(secondNumber);
        if (sparseArray.get(num1) == null) {
            sparseArray.put(num1, new SparseArray<String>());
        }
        temporarySparseArray = sparseArray.get(num1);
        temporarySparseArray.put(num2, countyName);
        sparseArray.put(num1, temporarySparseArray);
        temporarySparseArray = null;
    }

    public void test() {
        readFromList();
        String s = sparseArray.get(0).get(2);
        SparseArray sa = sparseArray.get(0);
        System.out.println(sa.size()); //should be 3
        System.out.println(s); // should be Baldwin
    }
}

要检索所有以num1 开头的县,比如 0,您只需使用:

SparseArray<String> startingWithZero = sparseArray.get(0);

仅供参考:SparseArrayintegersHashMap,因此并非所有内容都必须自动装箱(从Integerint,因为您不能将原始类型放入HashMap) .

EDIT2 你打印一维稀疏数组的地址。

public void printEverythingStartingWithZero() {
    SparseArray<String> subSparseArray = sparseArray.get(0); //You first need a 1D sparseArray
    int key = 0;
    for(int i = 0; i < subSparseArray.size(); i++) {
       key = subSparseArray.keyAt(i);
       String county = subSparseArray.get(key); //county is the String in place (0,key)
       System.out.println(county);
    }
}

您需要先检索一维sparseArray,并带有前导零。

【讨论】:

  • 非常感谢这段代码!我有个问题。如果我想返回所有 num1=1 的字符串,例如 String s=map.get(new Pair(1,i)),其中 i 来自 for 循环并从 0 迭代到 3200.. 有没有更好的实现这一目标的方法?
  • 您必须以任何一种方式循环,因为您想要整个列表的一个子集。但也许可以使用 2D sparseArray。让我检查一下。
  • 有可能,看我的补充。
  • 谢谢你,但是如何在startingWithZero中打印值?
  • 如何打印返回的对象?代码如下: Object obj = sparseArray.get(key); System.out.println(obj);这不是打印任何东西。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-06
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
  • 2015-02-15
  • 2020-06-05
相关资源
最近更新 更多