简体   繁体   中英

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. 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. 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 :

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.

Assuming (!) that the ratingLineData is well-formed, you could match both IDs as string and convert only the rating, if there's a match. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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