简体   繁体   English

我如何使此代码更高效?

[英]How would I make this code more efficient?

    public double getRating(long userID, long movieID) {

    double answer = -1;

    for(int i = 0; i < ratingLineData.length; i++){
        String[] temp = ratingLineData[i].split("\t");
        if(Long.parseLong(temp[0]) == userID && Long.parseLong(temp[1]) == movieID)
            return Long.parseLong(temp[2]);
    }



    return answer;
}

I have formatted lines of data, and so I want to check if the data at a certain spot of those lines is equal to the userID and movieID passed in, and if it is, I'll return the data at the 2nd element. 我已经格式化了数据行,因此我想检查这些行中某个位置的数据是否等于传入的userID和movieID,如果是,我将在第二个元素处返回数据。 My problem is probably where I split the line of data by the tab key, but I can't think of anything more efficient, possibly using indexOf, but if I use indexOf then it will also show if there is the user's ID or movie's ID in the time stamp, which would be a bad bug. 我的问题可能是我用Tab键将数据行分开了,但是我想不出什么更有效的方法,可能是使用indexOf,但是如果我使用indexOf,那么它还会显示是否有用户的ID或电影的ID在时间戳中,这将是一个错误。 Can someone give me pointers to what would be faster? 有人可以给我指出更快的方法吗?

I highlight few ways to optimize, there may be otherways also: 我重点介绍了几种优化方法,但也许还有其他方法:

public double getRating(long userID, long movieID) {

double answer = -1;
String[] temp = null; // Good to assign data outside the loop
int length = ratingLineData.length; // good practice

for(int i = 0; i < length; i++){
    temp = ratingLineData[i].split("\t");
    if(Long.parseLong(temp[0]) == userID && Long.parseLong(temp[1]) == movieID)
        return Long.parseLong(temp[2]);
}

return answer;
}

I can only see one obvious optimisation, which avoids the additional long -> double conversion : 我只能看到一个明显的优化,它避免了额外的long-> double转换:

public double getRating(long userID, long movieID) {

    double answer = -1;

    for(int i = 0; i < ratingLineData.length; i++) {
        String[] temp = ratingLineData[i].split("\t");
        if(Long.parseLong(temp[0]) == userID && Long.parseLong(temp[1]) == movieID)
            return Double.parseDouble(temp[2]);
    }
    return answer;
}

Even so, I'd measure it to be sure. 即使这样,我还是要对其进行测量。

Moving the String[] temp declaration outside the loop is unlikely to make any difference because it does not cause an object allocation. String[] temp声明移到循环外不会有任何区别,因为它不会引起对象分配。

Assuming (!) that the ratingLineData is well-formed, you could match both IDs as string and convert only the rating, if there's a match. 假设(!)ratingLineData格式正确,则可以将两个ID都匹配为字符串,并且如果存在匹配项,则仅转换评级。 If there are many searches, sorting and binary search would greatly improve matters. 如果搜索很多,排序和二进制搜索将大大改善问题。

public long getRating(long userID, long movieID) {
  String um = userID + "\t" + movieID + "\t";
  for(int i = 0; i < ratingLineData.length; i++){
    if( ratingLineData[i].startsWith( um ) ){
      return Long.parseLong( ratingLineData[i].substring( um.length() ));
    }
  }
  return -1L;
}

The most efficient code for your parsing should iterate all chars only once and shouldn't allocate new memory. 用于解析的最有效代码应仅将所有字符迭代一次,并且不应分配新的内存。 In other words, you just need a state machine like this: 换句话说,您只需要一个这样的状态机:

CharSequence[] ratingLineData = new String[]{"10\t1\t300", "10\t2\t400", "20\t1\t100"};

public double getRating(long userID, long movieID) {
    for (int i = 0; i < ratingLineData.length; i++) {
        final CharSequence line = ratingLineData[i];

        long currentUserID = 0;
        long currentMovieID = 0;
        long currentRating = 0;
        int currentColumn = 0;

        for (int j = 0; j < line.length(); j++) {
            final char c = line.charAt(j);
            switch (c) {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                    final int digit = c - '0';
                    switch (currentColumn) {
                        case 0:
                            currentUserID = currentUserID * 10 + digit;
                            break;
                        case 1:
                            currentMovieID = currentMovieID * 10 + digit;
                            break;
                        case 2:
                            currentRating = currentRating * 10 + digit;
                            break;
                    }
                    break;
                case '\t':
                    currentColumn++;
                    break;
                default:
                    break;
            }
        }
        if (currentUserID == userID && currentMovieID == movieID) {
            return currentRating;
        }
    }

    return -1;
}

System.out.println(getRating(5, 3));
System.out.println(getRating(10, 2));        
System.out.println(getRating(20, 1));
System.out.println(getRating(20, 2));

This example illustrates the following philosophy. 本示例说明了以下原理。 If someone is asking for the most efficient code for parsing, the answer is to build a specific state machine. 如果有人要求最有效的代码进行解析,则答案是构建特定的状态机。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM