java 去重字符串_Java之字符串去重的简述

java 去重字符串_Java之字符串去重的简述在编写 JS 代码时 我们发现可以通过 JSON 的特性消除重复数据 并快速的消除数据 下文是 Java 之字符串去重的简述 让爱站技术频道小编带你一起进入下文了解一下吧 字符串在任何应用中都占用了大量的内存 尤其数包含独立 UTF 16 字符的 char 数组对 JVM 内存的消耗贡献最多 因为每个字符占用 2 位 内存的 30 被字符串消耗其实是很常见的 不仅是因为字符串是与我们互动的最好的格式 而且是由于流行的 HT

在编写JS代码时,我们发现可以通过JSON的特性消除重复数据,并快速的消除数据,下文是Java之字符串去重的简述?让爱站技术频道小编带你一起进入下文了解一下吧!

字符串在任何应用中都占用了大量的内存。尤其数包含独立UTF-16字符的char[]数组对JVM内存的消耗贡献最多——因为每个字符占用2位。

内存的30%被字符串消耗其实是很常见的,不仅是因为字符串是与我们互动的最好的格式,而且是由于流行的HTTP API使用了大量的字符串。使用Java 8 Update 20,我们现在可以接触到一个新特性,叫做字符串去重,该特性需要G1垃圾回收器,该垃圾回收器默认是被关闭的。

字符串去重利用了字符串内部实际是char数组,并且是final的特性,所以JVM可以任意的操纵他们。

对于字符串去重,开发者考虑了大量的策略,但最终的实现采用了下面的方式:

无论何时垃圾回收器访问了String对象,它会对char数组进行一个标记。它获取char数组的hash value并把它和一个对数组的弱引用存在一起。只要垃圾回收器发现另一个字符串,而这个字符串和char数组具有相同的hash code,那么就会对两者进行一个字符一个字符的比对。

如果他们恰好匹配,那么一个字符串就会被修改,指向第二个字符串的char数组。第一个char数组就不再被引用,也就可以被回收了。

这整个过程当然带来了一些开销,但是被很紧实的上限控制了。例如,如果一个字符未发现有重复,那么一段时间之内,它会不再被检查。

那么该特性实际上是怎么工作的呢?首先,你需要刚刚发布的Java 8 Update 20,然后按照这个配置: -Xmx256m -XX:+UseG1GC 去运行下列的代码:

public class LotsOfStrings {

private static final LinkedListLOTS_OF_STRINGS = new LinkedList<>();

public static void main(String[] args) throws Exception {

int iteration = 0;

while (true) {

for (int i = 0; i < 100; i++) {

for (int j = 0; j < 1000; j++) {

LOTS_OF_STRINGS.add(new String(“String ” + j));

}

}

iteration++;

System.out.println(“Survived Iteration: ” + iteration);

Thread.sleep(100);

}

}

}

这段代码会执行30个迭代之后报OutOfMemoryError。

现在,开启字符串去重,使用如下配置去跑上述代码:

-Xmx256m -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics

此时它已经可以运行更长的时间,而且在50个迭代之后才终止。

JVM现在同样打印出了它做了什么,让我们一起看一下:

[GC concurrent-string-deduplication, 4658.2K->0.0B(4658.2K), avg 99.6%, 0.0 secs]

[Last Exec: 0.0 secs, Idle: 0.0 secs, Blocked: 0/0.0000000 secs]

[Inspected: ]

[Skipped: 0( 0.0%)]

[Hashed: (100.0%)]

[Known: 0( 0.0%)]

[New: (100.0%) 4658.2K]

[Deduplicated: (100.0%) 4658.2K(100.0%)]

[Young: 372( 0.3%) 14.5K( 0.3%)]

[Old: ( 99.7%) 4643.8K( 99.7%)]

[Total Exec: 4/0.0 secs, Idle: 4/0. secs, Blocked: 0/0.0000000 secs]

[Inspected: ]

[Skipped: 0( 0.0%)]

[Hashed: ( 99.8%)]

[Known: 903( 0.2%)]

[New: ( 99.8%) 21.2M]

[Deduplicated: ( 99.7%) 21.1M( 99.6%)]

[Young: 1101( 0.2%) 43.0K( 0.2%)]

[Old: ( 99.8%) 21.1M( 99.8%)]

[Table]

[Memory Usage: 81.1K]

[Size: 2048, Min: 1024, Max: ]

[Entries: 2776, Load: 135.5%, Cached: 0, Added: 2776, Removed: 0]

[Resize Count: 1, Shrink Threshold: 1365(66.7%), Grow Threshold: 4096(200.0%)]

[Rehash Count: 0, Rehash Threshold: 120, Hash Seed: 0x0]

[Age Threshold: 3]

[Queue]

[Dropped: 0]

为了方便,我们不需要自己去计算所有数据的加和,使用方便的总计就可以了。

上面的代码段规定执行了字符串去重,花了16ms的时间,查看了约 120 k 字符串。

上面的特性是刚推出的,意味着可能并没有被全面的审视。具体的数据在实际的应用中可能看起来有差别,尤其是那些应用中字符串被多次使用和传递,因此一些字符串可能被跳过或者早就有了hashcode(正如你可能知道的那样,一个String的hash code是被懒加载的)。

在上述的案例中,所有的字符串都被去重了,在内存中移除了4.5MB的数据。

[Table]部分给出了有关内部跟踪表的统计信息,[Queue]则列出了有多少对去重的请求由于负载被丢弃,这也是开销减少机制中的一部分。

那么,字符串去重和字符串驻留相比又有什么差别呢?事实上,字符串去重和驻留看起来差不多,除了暂留的机制重用了整个字符串实例,而不仅仅是字符数组。

JDK Enhancement Proposal 192的创造者的争论点在于开发者们常常不知道将驻留字符串放在哪里合适,或者是合适的地方被框架所隐藏.就像我写的那样,当碰到复制字符串(像国家名字)的时候,你需要一些常识.字符串去重,对于在同一个JVM中的应用程序的字符串复制也有好处,同样包括像XML Schemas,urls以及jar名字等一般认为不会出现多次的字符串.

当字符串驻留发生在应用程序线程中的时候,垃圾回收异步并发处理时,字符串去重也不会增加运行时的消耗.这也解释了,为什么我们会在上面的代码中发现Thread.sleep().如果没有sleep会给GC增加太多的压力,这样字符串去重根本就不会发生.但是,这只是示例代码才会出现的问题.实际的应用程序,常常会在运行字符串去重的时候使用几毫秒的时间.

通过爱站技术频道小编介绍的Java之字符串去重的简述,相信大家都有了一定的了解,如需了解更多的相关资讯,请继续关注爱站技术频道吧!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/208688.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月19日 上午10:59
下一篇 2026年3月19日 上午11:00


相关推荐

  • OpenClaw(Clawdbot)+Skills集成小白教程:2026年京东云一键部署基础教学

    OpenClaw(Clawdbot)+Skills集成小白教程:2026年京东云一键部署基础教学

    2026年3月13日
    3
  • 闭包的优缺点

    闭包的优缺点闭包的好处有 1 缓存 2 面向对象中的对象 3 实现封装 防止变量跑到外层作用域中 发生命名冲突 4 匿名自执行函数 匿名自执行函数可以减小内存消耗 闭包的坏处 1 内存消耗 通常来说 函数的活动对象会随着执行期上下文一起销毁 但是 由于闭包引用另外一个函数的活动对象 因此这个活动对象无法被销毁 这意味着 闭包比一般的函数需要更多的内存消耗 尤其在 IE 浏览器中需要关注 由于 IE 使用非原生 javascript 对象实现 DOM 对象 因此闭包会导致内存泄露问题

    2026年3月19日
    3
  • AlertDialog的六种创建方式

    AlertDialog的六种创建方式AlertDialog 的六种创建方式 nbsp AlertDialog 的六种创建方式创建 AlertDialog 的步骤 1 创建 AlertDialog Builder 对象 2 调用 Builder 对象的 setTitle 方法设置标题 setIcon 方法设置图标 3 调用 Builder 相关方法如 setMessage 方法 setItems 方法 setSingleCho 方法 setMultiCh

    2025年6月7日
    5
  • windows下如何安装Composer?

    windows下如何安装Composer?

    2021年10月21日
    51
  • 为CentOS安装防DDOS攻击软件DDoS-Deflate

    为CentOS安装防DDOS攻击软件DDoS-DeflateDDoS Deflate 是一款非常小巧的防御和减轻 DDoS 攻击的工具 它可以通过监测 netstat 来跟踪来创建大量互联网连接的 IP 地址信息 通过 APF 或 IPTABLES 禁止或阻档这些非常 IP 地址 我们可以使用 netstat 命令查看当前系统连接的状态 是否有受到 DDOS 攻击 root localhost netstat ntu awk print 5 cut d

    2026年3月26日
    2
  • spring boot 系列之五:spring boot 通过devtools进行热部署

    前面已经分享过四篇随笔:在上述代码操作的过程中肯定也发现了一个问题:哪怕是一个个小小的修改,都必须要重新启动服务才能使修改生效。那能不能通过配置实现springboot的热部署呢?答案是肯定的。

    2022年2月16日
    43

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号