Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 避免创建';新';使用特定字符集将字节[]转换为字符串时的字符串对象_Java_String_Character Encoding_Pool - Fatal编程技术网

Java 避免创建';新';使用特定字符集将字节[]转换为字符串时的字符串对象

Java 避免创建';新';使用特定字符集将字节[]转换为字符串时的字符串对象,java,string,character-encoding,pool,Java,String,Character Encoding,Pool,我正在读取一个二进制文件,想把字节转换成ASCII字符串。有没有办法在不调用String上的new的情况下执行此操作,以避免在字符串文本池中创建多个语义相同的String对象?我认为这可能是不可能的,因为这里不可能引入使用双引号的String对象。这是正确的吗 private String nextString(DataInputStream dis, int size) throws IOException { byte[] bytesHolder = new byte[size];

我正在读取一个二进制文件,想把字节转换成ASCII字符串。有没有办法在不调用
String
上的
new
的情况下执行此操作,以避免在字符串文本池中创建多个语义相同的
String
对象?我认为这可能是不可能的,因为这里不可能引入使用双引号的
String
对象。这是正确的吗

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();
您可以对字符串调用intern()方法,以确保整个JVM都有一个intern()方法

String s = new String(bytes, "US-ASCII").intern();
您不会避免再次创建初始字符串,但会在存储上保存


也就是说,插入字符串的存储空间有限,因此请谨慎使用。更好的选择可能是使用字符串作为键和值实现HashMap,并检查字符串是否已经存在,如果已经存在则获取它,如果不存在则插入它。这样就不会有这样的内存限制。

必须有一个缓存将字节数组映射到字符串,然后在创建新字符串之前在缓存中搜索任何相等的值

您可以使用Yishai发布的
intern()
插入现有字符串-这不会阻止您创建更多字符串,但会使除第一个字符串(对于任何字符序列)外的所有字符串都非常短暂。另一方面,它将使所有不同的字符串确实存在很长时间

您可以使用
映射进行“伪实习”:

您甚至可以投入更多的精力,最终得到一个LRU缓存,这样它将保留N个最近获取的字符串,在需要时丢弃其他字符串


正如我所说,所有这些都不会减少最初创建的字符串的数量,但这在您的情况下可能是个问题吗?GCs已经过调整,使得创建短期对象的成本非常低。

除非您分析了应用程序并确定创建的
字符串是问题的确切根源,否则您不应该担心它


如果您发现
字符串
的创建是您问题的根源,我会推荐您的建议,即从
字节[]
字符串
的映射。这与您的
字符串
的效果大致相同,但在重新启动VM之前不会占用宝贵的内存。

如果要对它们进行垃圾收集,则调用“new”不是问题,我更关心池中字符串的数量。但你说得对,使用intern()时,他们可能太“长寿”。想一想。啊,我不知道实习生()。我会去实习,看看是否值得。没有“普通对象池”。你在说什么?@erickson:我是说JVM的堆和字符串文本池。
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;