Algorithm

709-To Lower Case,Easy
Implement function ToLowerCase() that has a string parameter str, and returns the same string in lowercase.

这题其实不难,把字母的ASCII码从大写(65-90)转换成小写(97-122)就行了,进阶的话可以参考Java源码String的toLowerCase方法。

1
2
3
4
5
6
7
8
9
10
11
public String toLowerCase(String str) {
char[] cs = str.toCharArray();
for (int i = 0; i < cs.length; i++) {
char c = cs[i];
if (c >= 65 && c <= 90) {
c += 32;
}
cs[i] = c;
}
return new String(cs);
}

Review

Understanding the G1 Garbage Collector – Java 9

Java9 Hotspot开始把G1 GC作为默认收集器,文章分为下面几部分:

  • 介绍现代GCs把Heap分为新生代和老年代,因为研究表明,超过90%的对象在第一次GC的时候会被回收,还有介绍了新生代分为Eden和Survivor区。
  • 介绍G1的优点:1)大部分工作可并发,2)使用不连续内存空间。
  • G1可以同时回收新生代和老年代,不同于其他回收器分为Eden,Surcivor和Old3块空间,G1把Heap分为许多很小的固定(默认2M)空间,使得回收速度更快(空间小)以及回收可选性更高。
  • G1的意思是Garbage First,可以配置-XX:MaxGCPauseMillis=n设置G1最大停止时间,G1会以这个数值为目标优化回收算法。

Tip

  • 循环体内,字符串的连接方式,用StringBuilder的append方法,反编译出来的代码显示每次循环都会new一个StringBuilder对象进行append操作
  • 用+拼接2个确定的字符串,JVM会优化成1个字符串
    1
    2
    3
    String str1 = "he" + "llo";
    String str2 = "hello";
    System.out.println(str1 == str2);

答案是true,字符串常量池只有”hello”,没有”he”和”llo”。

  • 对 trace/debug/info 级别的日志输出,必须使用条件输出形式或者使用占位符的方式。
    1
    logger.debug("Uploading image with id: " + id + " and url: " + url);

如果日志级别是 warn,上述日志不会打印,但是会执行字符串拼接操作,如果 url 是对象, 会执行toString()方法,浪费了系统资源,执行了上述操作,最终日志却没有打印。

1
logger.debug("Uploading image with id: {} and url : {} ", id, url);

Share

关于Java中字符串类String的设计

String在Java设计成final,意思就是不可变,这样设计的好处有:

  1. 天然线程安全
  2. 安全,因为不可变,例如数据库链接字符串在JVM中创建后就不用担心被篡改
  3. 字符串常量池的设计
    因为Stirng设计成final,才可以设计字符串常量池,如果String是可变的。
    1
    2
    3
    String str1 = "hello";
    String str2 = "hello";
    str2 = "HELLO";

这时候str1也会变成HELLO。
JVM为了提高性能和减少内存开销,在实例化字符串常量的时候进行了一些优化

  • 为字符串开辟一个字符串常量池,类似于缓存区
  • 创建字符串常量时,首先坚持字符串常量池是否存在该字符串
  • 存在该字符串,返回引用实例,不存在,实例化该字符串并放入池中
    字符串常量池存放在方法区,方法区(method area)是JVM规范的一个概念,用于存储类信息,常量池,静态变量和JIT编译后的代码,永久代是Hotspot虚拟机的概念,是方法区的一种实现。
    Java8移除了永久代,取而代之的是一块与Heap不相连的本地内存(Native memory)-元空间(Metaspace),元空间存储类的元信息,静态变量和常量池并入Heap中。