5

バイナリ ファイルから読み込んでいて、バイトを US ASCII 文字列に変換したいと考えています。文字列リテラルプールに複数の意味的に等しいオブジェクトが作成されるのを避けるためnewに、これを行う方法はありますか? ここではダブルクォートを使ったオブジェクトの導入ができないので、おそらく無理だと思っています。これは正しいです?StringStringString

private String nextString(DataInputStream dis, int size)
throws IOException
{
  byte[] bytesHolder = new byte[size];
  dis.read(bytesHolder);
  return new String(bytesHolder, Charset.forName("US-ASCII")).trim();
4

3 に答える 3

3

文字列に対して intern() メソッドを呼び出して、JVM 全体に対して 1 つ確保することができます。

String s = new String(bytes, "US-ASCII").intern();

最初の文字列を再度作成することは避けられませんが、ストレージを節約できます。

そうは言っても、インターンされた文字列のストレージ スペースは限られているため、注意して使用してください。より良いオプションは、文字列をキーと値として HashMap を実装し、文字列が既に存在するかどうかを確認し、存在する場合は取得し、存在しない場合は挿入することです。そうすれば、そのようなメモリ制限はありません。

于 2009-10-16T14:33:19.647 に答える
3

バイト配列を文字列にマッピングするキャッシュが必要であり、新しい文字列を作成する前に、キャッシュを検索して等しい値を探す必要があります。

intern()Yishaiが投稿したように、既存の文字列をインターンすることができます. 一方で、それはすべての個別の文字列を実際に非常に長い間存続させます。

を使用して「疑似インターニング」を行うことができますMap<String, String>

String tmp = new String(bytesHolder, Charset.forName("US-ASCII")).trim();
String cached = cache.get(tmp);
if (cached == null)
{
    cached = tmp;
    cache.put(tmp, tmp);
}
return cached;

もう少し努力して、LRU キャッシュで終わることもできます。これにより、最近フェッチされた N 個の文字列が保持され、必要に応じて他の文字列が破棄されます。

私が言うように、そもそも作成される文字列の数を減らすものはありませんが、それはあなたの状況で問題になる可能性がありますか? GC は、存続期間の短いオブジェクトの作成が非常に安価になるように調整されています。

于 2009-10-16T14:37:06.240 に答える