近来要加载许多数据库数据到内存,
这些数据有很多是重复的。
在反复测试之后
发现intern() 省了好多内存。
举例如下:
以下是表信息:
mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 8000 |
+----------+
1 row in set (0.01 sec)
mysql> select name From t1 limit 0,1;
+--------------------------------------+
| name |
+--------------------------------------+
| 123456789123456789123456789 |
+--------------------------------------+
1 row in set (0.00 sec)
总共8000行 ,每行的数据都是 "123456789123456789123456789"
下面是类 (连接异常忽略)
public static void a1() throws SQLException {
List<Po> list = new ArrayList<Po>();
Connection con = DB.getCon();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT name FROM t1");
while (rs.next()) {
String s = rs.getString(1);
Po o = new Po();
//o.setName(s); //注释掉
o.setName(s.intern());
list.add(o);
s=null;
o = null;
}
rs.close();
stmt.close();
con.close();
}
public static void a2() throws SQLException {
List<Po> list = new ArrayList<Po>();
Connection con = DB.getCon();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT name FROM t1");
while (rs.next()) {
String s = rs.getString(1);
Po o = new Po();
o.setName(s);
list.add(o);
s=null;
o = null;
}
rs.close();
stmt.close();
con.close();
}
注意着色部分,
a1 方法测试 使用内存: 2046544
a2 方法测试 使用内存: 3475000
如果在函数的结尾加上 System.gc(); 去除connection 的影响
a1 方法测试 使用内存: 668856
a2 方法测试 使用内存:2262232
然后再把 写函数 a3() ,把rs.getString(1) 换为 get()
static String get() {
return "123456789123456789123456789123456789123456789";
}
public static void a3() throws SQLException {
List<Po> list = new ArrayList<Po>();
Connection con = DB.getCon();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT name FROM t1");
while (rs.next()) {
String s = get();
Po o = new Po();
o.setName(s);
list.add(o);
s=null;
o = null;
}
rs.close();
stmt.close();
con.close();
}
a3 方法测试 使用内存:666536
a2 (668856)比a3 的内存使用量多了一点点,这个估计就是常量池那一点内存
8000条数据 差别这么大, 数据量再大的话,优势更加明显.
建议大家在连接数据库查询出来的数据,用intern();
注:内存使用 用 Runtime.getRuntime().totalMemory()-Runtime.getRuntime().freeMemory() 计算
都是不同的数据就没有必要了,
我这个测试是放大了 有了重复数据后 intern() 的影响
用不用视情况而定吧.
分享到:
相关推荐
这篇文章将要讨论 Java 6 中是如何实现 String.intern 方法的,以及这个方法在 Java 7 以及 Java 8 中做了哪些调整。
java中String类的intern、split方法的详细讲解。
受此问题的启发而被关闭:“ API请求:string.Intern(ReadOnlySpan ...)” 共享池已设置上限; 具有第二代LRU驱逐,以及第二代GC集合的进一步驱逐。 使用示例 馆藏 using Ben . Collections ; array = array . ...
那么String.intern的性能怎么样呢?我们一起来看一下。 String.intern和G1字符串去重的区别 之前我们提到了,String.intern方法会返回字符串常量池中的字符串对象的引用。 而G1垃圾回收器的字符串去重的功能其实和...
关于String.intern()方法,这个问题都被问烂了,有的文章在分析的时候还在用jdk1.7,jdk1.8之后内存模型发生了变化,内存的变化也会影响intern方法的执行,这里有必要写文章分析一下,请大家务必从头开始看,这样...
主要给大家介绍了关于java String中intern的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
本文将给大家详细介绍关于C#字符串优化String.Intern、IsInterned的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。 首先看一段程序: using System; class Program { static void ...
深入理解JavaString#intern()内存模型Java开发Java经验技巧共4页.pdf.zip
pos文件是ProcessOn的源文件,可以导入后直接打开编辑。 内容是:不同jdk版本下对String的intern()的分析
深入理解 Java String#intern() 内存模型.docx
主要介绍了Java String的intern用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
本文主要介绍java 中String 的intern方法,这里主要通过实例来说明不同版本的JDK,intern方法的对比,有需要的小伙伴可以参考下
string常量池和intern_韩雅茹Java系列2021.pdf
大家知道,Java中string.intern()方法调用会先去字符串常量池中查找相应的字符串,如果字符串不存在,会在字符串常量池中创建该字符串然后再返回。 字符串常量池是一个固定大小的HashMap,桶的数量默认是1009, ...
主要介绍了通过String.intern()方法浅谈堆中常量池,在JDK7之前,字符串常量是存在永久带Perm 区的,JDK7开始在将常量池迁移到堆中,这个变化也导致了String的新特性,下面我们慢慢进行介绍。,需要的朋友可以参考下
String.intern()是一个Native方法,底层调用C++的 StringTable::intern 方法,源码注释:当调用 intern 方法时,如果常量池中已经该字符串,则返回池中的字符串;否则将此字符串添加到常量池中,并返回字符串的...
在JDK6.0中,StringTable的长度是固定的,长度就是1009,因此如果放入String Pool中的String非常多,就会造成hash冲突,导致链表过长,当调用String#intern()时会需要到链表上一个一个找,从而导致性能大幅度下降;...
//true}补充:String对象的intern方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String对象的equals结果是