当前位置: 首页 > 面试题库 >

Java中String轻量级实现的最佳替代方案

张权
2023-03-14
问题内容

我的应用程序是带有密集字符串处理的多线程。我们正在经历过多的内存消耗,并且性能分析表明这是由于String数据引起的。我认为使用某种flyweight模式实现甚至是缓存将极大地受益于内存消耗(我可以肯定Strings通常是重复的,尽管我在这方面没有任何硬数据)。

我看过Java常量池和String.intern,但似乎可以引发一些PermGen问题。

在Java中实现应用程序范围的多线程字符串池的最佳替代方法是什么?


问题答案:

注意:此答案使用的示例可能与现代运行时JVM库无关。 特别是,该substring示例在OpenJDK / Oracle 7+中不再是问题。

我知道这与人们经常告诉您的内容背道而驰,但是有时显式创建新String实例 可能 是减少内存的重要方法。

由于字符串是不可变的,因此有几种方法可以利用该事实并共享支持字符的数组以节省内存。但是,有时这可以通过防止垃圾回收那些数组未使用的部分来实际上增加内存。

例如,假设您正在解析日志文件的消息ID,以提取警告ID。您的代码如下所示:

//Format:
//ID: [WARNING|ERROR|DEBUG] Message...
String testLine = "5AB729: WARNING Some really really really long message";

Matcher matcher = Pattern.compile("([A-Z0-9]*): WARNING.*").matcher(testLine);
if ( matcher.matches() ) {
    String id = matcher.group(1);
        //...do something with id...
}

但是看看实际存储的数据:

    //...
    String id = matcher.group(1);
    Field valueField = String.class.getDeclaredField("value");
    valueField.setAccessible(true);

    char[] data = ((char[])valueField.get(id));
    System.out.println("Actual data stored for string \"" + id + "\": " + Arrays.toString(data) );

这就是整个测试行,因为匹配器只是在相同的字符数据周围包装了一个新的String实例。当您更换比较结果String id = matcher.group(1);String id = new String(matcher.group(1));



 类似资料:
  • 谷歌云功能的运作方式似乎是: 你的模块进入一个目录 这很奇怪,因为: 即使模块<代码>一个。js和两个。js在运行时需要不同的包,即共享的意味着它们的启动时间将比单独启动慢,因为它们都需要安装包的所有依赖项,而不仅仅是它们自己的 因此,确保云功能以尽可能轻的运行时占用空间以最佳方式运行的最佳实践是什么?谷歌的设计决策似乎意味着,你做的云功能越多,那么每个云功能中捆绑的垃圾就越多,速度越慢,成本也越

  • 我有 2 个实体(父实体和子实体),它们之间具有一对多关系。 “父项具有子项列表”,“子项具有父项”字段。 孩子有 在父字段中。 家长有 在子列表中。 我想找到一种方法,用另一个家长替换一个孩子的家长。(即将子女A的父母从父母A变更为父母B) 因为我想遵循父列表,所以我想从列表中删除子项。问题是,即使我首先将ChildA添加到ParentB的列表中,也要将ChildA的Parent字段设置为Par

  • 问题内容: 我看过这样的例子: 并假设我可以有一个Constants类来包装常量,并声明它们为static final。我几乎不了解Java,并且想知道这是否是创建常量的最佳方法。 问题答案: 这是完全可以接受的,甚至可能是标准。 类型是哪里,是所有大写字母的名称,下划线带有空格,并且VALUE是常量值; 我强烈建议不要将常量放在自己的类或接口中。 附带说明:声明为final且可变的变量仍然可以更

  • 我正在进行从Weblogic到Websphere的服务器迁移项目。问题是,在Weblogic中,我们已经在Weblogics中使用了一个指定为Startup类的类(以及log4j配置文件等类的参数),该类存在于一个jar中,该jar通过编辑启动脚本添加到Weblogic类路径中。这个jar初始化一个全局log4j文件,该文件用于服务器上部署的所有应用程序,而不是任何特定应用程序。每个应用程序都通过

  • 问题内容: replace方法返回一个字符串对象而不是替换给定字符串的内容这一事实有点让人费解(但是,当您知道字符串在Java中是不可变的时,这是可以理解的)。通过在某些代码中使用深度嵌套的替换,我的性能受到了重大影响。有什么我可以替换的东西可以使它更快吗? 问题答案: 这就是StringBuilder的目的。如果要进行很多操作,请在上进行操作,然后在需要时将其转换为。 因此描述: “可变的字符序

  • 问题内容: 我(使用Java)正在研究一种递归图像处理算法,该算法以递归方式从中心点向外遍历图像的像素。 不幸的是,这会导致堆栈溢出。因此,我决定切换到基于队列的算法。 现在,这一切都很好而且很花哨- 但考虑到以下事实:它的队列将在非常短的时间内分析成千上万个像素,同时不断弹出并推动,而不会保持可预测的状态(长度可能在100到100之间,和20000),则队列实现需要具有显着的快速弹出和推送功能。