简体   繁体   中英

How to convert Parse ObjectId (String) to long?

Every object in Parse.com has your own ObjectId, that is a string with 10 char and apparently it is created by this regex: [0-9a-zA-Z]{10} .

Example of ObjectId in Parse:

  • X12wEq4sFf
  • Weg243d21s
  • zwg34GdsWE

I would like to convert this String to Long, because it will save memory and improve searching. (10 chars using UTF-8 has 40 bytes, and 1 long has 8 bytes)

If we calculate the combinations, we can find:

  • String ObjectId: 62^10 = 839299365868340224 different values;
  • long: is 2^64 = 18446744073709551616 different values.

So, we can convert these values without losing information. There is a simple way to do it safely? Please, consider any kind of encoding for Chars (UTF-8, UTF-16, etc);

EDIT: I am just thinking in a hard way to solved it. I am asking if there is an easy way.

  1. Your character set is a subset of the commonly-used Base64 encoding, so you could just use that. Java has the Base64 class, no need to roll your own codec for this.
  2. Are you sure this is actually valuable? "because it will save memory and improve searching" seems like an untested assertion; saving a few bytes on the IDs may very well be offset by the added cost of encoding and decoding every time you want to use something.

EDIT: Also, why are you using UTF-8 strings for guaranteed-ascii data? If you represent 10 char IDs as a byte[10] , that's just 10 bytes instead of 40 (ie much closer to the 8 for a long ). And you don't need to do any fancy conversions.

Here's a straightforward solution using 6 bits to store a single character.

public class Converter {

    private static final String CHARS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; 

    private static int convertChar(char c) {
        int ret = CHARS.indexOf( c );
        if (ret == -1)
            throw new IllegalArgumentException( "Invalid character encountered: "+c);
        return ret;
    }

    public static long convert(String s) {
        if (s.length() != 10)
            throw new IllegalArgumentException( "String length must be 10, was "+s.length() );
        long ret = 0;
        for (int i = 0; i < s.length(); i++) {
            ret = (ret << 6) + convertChar( s.charAt( i ));
        }
        return ret;
    }
}

I'll leave the conversion from long to String for you to implement, it's basically the same in reverse.

Ps: If you really want to save space, don't use Long , it adds nothing compared to the primitive long except overhead.

Ps 2: Also note that you aren't really saving much with this conversion: storing the ASCII characters can be done in 10 bytes, while a long takes up 4. What you save here is mostly the overhead you'd get if you stored those 10 bytes in a byte array.

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