文字列と数値のどちらを選択しますか?

3339 ワード


私の長年の開発経験の中で、よく発見された1つの状況は、多くのプロジェクトのオブジェクトフィールドやデータベースフィールドがもともと数字タイプだったのに、文字列タイプとして定義されていることです.これは関係ありませんか?
小さなプロジェクトでは、影響はないかもしれませんが、どうせビジネスロジックが正しい限り、パフォーマンスに問題はありません.データも多くないし、ユーザーも多くありません.
しかし、ビッグデータ処理では、文字列からデジタルタイプに置き換えることで、メモリ、ディスクストレージ、ネットワーク帯域幅を大幅に節約し、IOのコストを削減することができ、多くのデータ構造とアルゴリズムは文字列よりもデジタルタイプを使用するのが速い.
例を見てみましょう.多くのログを処理する必要があると仮定します.各ログには、このようなフォーマットを識別する唯一のIDがあります.
F5051582611729507844
3832154813577306424
F1624235934976711017
3810376634214027595
F6884923813121317381
7278044081826528150

 
これらの標識を見て、どう思いますか.私の最初の反応は数字だったはずだが、どうしてFがあるのだろうか.16進法として使えると思います.後にFを負の記号とすることができることが分かった.これは64ビットの長整型である.
では、これらの標識を文字列と見なすと、どんな違いがありますか?
もちろん、このようなログを毎秒百万または千万件処理すると、各処理結果には百万または千万のこのような識別要素からなる集合が含まれる可能性があります.この違いは非常に明らかになります.
次に、3832154813577306424を識別するストレージの使用状況を分析します.
1、メモリ使用量
文字列として:JAVAでは文字列が文字で構成されており、1文字は2バイトで構成されており(これはJAVAの悲劇である)、上記の標識は19文字あるため、占有メモリサイズは19*2+4=42(バイト)、+4は文字列が文字列を1つの整数で保存するハッシュ値であるためである.
≪数値として|As Number|emdw≫:長整数の場合、使用するメモリのサイズは8バイトです.
ここは5倍以上の差があるでしょう.
2、バイトサイズのシーケンス化
ネットワークを介してこれらのIDを転送する必要がある場合や、これらのIDをディスクに格納する必要がある場合、これらのIDをバイト配列に変換する必要があります.どのようにバイト配列に変換しますか?多様な符号化方式を用いることができる.
文字列として:JAVAで文字列をバイト配列に変換するには、複数の符号化方法が使用できることを知っています.一般的な符号化方法では、上記の文字列を符号化したバイト数を見てみましょう.
String abc = "3832154813577306424";

System.out.println("3832154813577306424 length:"+abc.length());
System.out.println(Charset.defaultCharset().name()+":"+abc.getBytes().length);
System.out.println("unicode:"+abc.getBytes("unicode").length);
System.out.println("gbk:"+abc.getBytes("gbk").length);
System.out.println("gb2312:"+abc.getBytes("gb2312").length);
System.out.println("ISO-8859-1:"+abc.getBytes("ISO-8859-1").length);

 
出力は次のとおりです.
3832154813577306424 length:19
UTF-8:19
unicode:40
gbk:19
gb2312:19
ISO-8859-1:19

 
≪数値として|As Number|emdw≫:長整数の場合、使用するメモリのサイズは8バイトです.
ここは2倍以上の差があるでしょう.
では、長整数型とバイト配列の間でどのように変換しますか?
String abc = "3832154813577306424";

System.out.println("3832154813577306424 length:"+abc.length());
System.out.println("long:"+ByteUtils.longToBytes(Long.parseLong(abc)).length);
byte[] bytes = ByteUtils.longToBytes(Long.parseLong(abc));
System.out.println("string:"+ByteUtils.bytesToLong(bytes));

 
出力は次のとおりです.
3832154813577306424 length:19
long:8
string:3832154813577306424

 
public static byte[] longToBytes(long x) {
    ByteBuffer longBuffer = ByteBuffer.allocate(Long.BYTES);
    longBuffer.putLong(0, x);
    return longBuffer.array();
}
public static long bytesToLong(byte[] bytes) {
    return bytesToLong(bytes, 0, bytes.length);
}
public static long bytesToLong(byte[] bytes, int offset, int length) {
    ByteBuffer longBuffer = ByteBuffer.allocate(Long.BYTES);
    longBuffer.put(bytes, offset, length);
    longBuffer.flip();//need flip
    return longBuffer.getLong();
}