编写高质量代码: 改善Java程序的151个建议 | 第四章 字符串

文章介绍了Java编程中关于字符串的一系列建议,包括使用String直接量赋值以优化内存使用,注意方法参数的正则要求,正确选择String、StringBuffer、StringBuilder以提高连接性能,理解字符串在表达式中的位置影响,选择合适的拼接方式以提升效率,推荐在复杂操作中使用正则表达式,以及强调使用UTF-8编码的重要性,并提示在字符串排序时考虑文化差异。
摘要由CSDN通过智能技术生成


在这里插入图片描述

编写高质量代码: 改善Java程序的151个建议

第四章 字符串

建议52:推荐使用String直接量赋值
  • 一般对象都是通过new关键字生成,String还有第二种生成方式,即直接声明方式,如String str = “a”;String中极力推荐使用直接声明的方式,不建议使用new String(“a”)的方式赋值。

    **原因:直接声明方式:**创建一个字符串对象时,首先检查字符串常量池中是否有字面值相等的字符串,如果有,则不再创建,直接返回池中引用,若没有则创建,然后放到池中,并返回新建对象的引用。

    **使用new String()方式:**直接声明一个String对象是不检查字符串常量池的,也不会吧对象放到池中。String的intern方法会检查当前的对象在对象池中是否有字面值相同的引用对象,有则返回池中对象,没有则放置到对象池中,并返回当前对象。

    public class Suggest52 {
        public static void main(String[] args) {
            String str1 = "Rocky编程日记";
            String str2 = "Rocky编程日记";
            String str3 = new String("Rocky编程日记");
            String str4 = str3.intern();
            System.out.println("两个直接量是否相等: " + (str1 == str2));
            System.out.println("直接量和对象是否相等: " + (str1 == str3));
            System.out.println("经过intern处理后的对象与直接量是否相等: " + (str1 == str4));
        }
    }
    
建议53:注意方法中传递的参数要求
  • replaceAll方法传递的第一个参数是正则表达式

    public class Suggest53 {
        public static void main(String[] args) {
    //        是
    //        蓝蓝的天,
    //        $是$
            System.out.println(StringUtils.remove("好是好","好"));
            System.out.println(StringUtils.remove("蓝蓝的天,白云飘","白云飘"));
            System.out.println(StringUtils.remove("$是$","$"));
        }
    }
    
    class StringUtils {
        // 删除字符串
        public static String remove(String source, String sub) {
            return source.replaceAll(sub,"");
        }
    }
    
建议54:正确使用String、StringBuffer、StringBuilder
  • String使用“+”进行字符串连接,之前连接之后会产生一个新的对象,所以会不断的创建新对象,优化之后与StringBuilder和StringBuffer采用同样的append方法进行连接,但是每一次字符串拼接都会调用一次toString方法,所以会很耗时。StringBuffer与StringBuilder基本相同,只是一个字符数组的在扩容而已,都是可变字符序列,不同点是:StringBuffer是线程安全的,StringBuilder是线程不安全的
建议55:注意字符串的位置
  • 在“+”表达式中,String字符串具有最高优先级)(Java对加号“+”的处理机制:在使用加号进行计算的表达式中,只要遇到String字符串,则所有的数据都会转换为String类型进行拼接,如果是原始数据,则直接拼接,如果是对象,则调用toString方法的返回值然后拼接。

    public class Suggest55 {
        public static void main(String[] args) {
            String str1 = 1 + 2 + " apple";
            String str2 = "apples:" + 1 + 2;
            System.out.println(str1);// 3 apple
            System.out.println(str2);// apples:12
        }
    }
    
建议56:自由选择字符串拼接方式
  • 字符串拼接有三种方法:

    加号、concat方法及StringBuilder(或StringBuffer)的append方法。

    字符串拼接性能中,StringBuilder的append方法最快,concat方法次之,加号最慢。

    原因:

    1. “+”方法拼接字符串:虽然编译器对字符串的加号做了优化,使用StringBuidler的append方法进行追加,但是与纯粹使用StringBuilder的append方法不同:一是每次循环都会创建一个StringBuilder对象,二是每次执行完都要调用toString方法将其准换为字符串–toString方法最耗时;
    2. concat方法拼接字符串:就是一个数组拷贝,但是每次的concat操作都会新创建一个String对象,这就是concat速度慢下来的真正原因;
    3. append方法拼接字符串:StringBuidler的append方法直接由父类AbstractStringBuilder 实现,整个append方法都在做字符数组处理,没有新建任何对象,所以速度快
    public class Suggest56 {
        public static void main(String[] args) {
            demo1();
            System.gc();
            demo2();
            System.gc();
            demo3();
            System.gc();
            demo4();
        }
    
        private static void demo1() {
            long startTime = System.nanoTime();
            StringBuilder sb = new StringBuilder("a");
            for (int i = 0; i < 50000; i++) {
                sb.append("c");
            }
            String str = sb.toString();
            long endTime = System.nanoTime();
            System.out.println("demo01 cost " + (endTime - startTime) + " ms");
        }
    
        private static void demo2() {
            long startTime = System.nanoTime();
            String sb = new String("a");
            for (int i = 0; i < 50000; i++) {
                sb += "c";
            }
            long endTime = System.nanoTime();
            System.out.println("demo02 cost " + (endTime - startTime) + " ms");
        }
        private static void demo3() {
            long startTime = System.nanoTime();
            String sb = new String("a");
            for (int i = 0; i < 50000; i++) {
                sb.concat("c");
            }
            long endTime = System.nanoTime();
            System.out.println("demo03 cost " + (endTime - startTime) + " ms");
        }
        private static void demo4() {
            long startTime = System.nanoTime();
            StringBuffer sb = new StringBuffer("a");
            for (int i = 0; i < 50000; i++) {
                sb.append("c");
            }
            long endTime = System.nanoTime();
            System.out.println("demo04 cost " + (endTime - startTime) + " ms");
        }
    
    }
    
    
    demo01 cost 3563600 ms
    demo02 cost 1704332800 ms
    demo03 cost 3631100 ms
    demo04 cost 2863500 ms
    
建议57:推荐在复杂字符串操作中使用正则表达式
  • 正则表达式是恶魔,威力强大,但难以控制

    public class Suggest57 {
        public static void main(String[] args) {
            // demo01();
            demo02();
        }
    
        private static void demo01() {
            // 接收键盘输入
            Scanner input = new Scanner(System.in);
            while (input.hasNext()) {
                String str = input.nextLine();
                int wordsCount = str.split(" ").length;
                System.out.println(str + " 单词数: " + wordsCount);
            }
        }
    
        private static void demo02() {
            // 接收键盘输入
            Scanner input = new Scanner(System.in);
            while (input.hasNext()) {
                String str = input.nextLine();
                // 正则表达式对象
                Pattern pattern = Pattern.compile("\\b\\w+\\b");
                // 生成匹配器
                Matcher matcher = pattern.matcher(str);
                // 记录单词数量
                int wordsCount = 0;
                // 遍历查找匹配
                while (matcher.find()) {
                    wordsCount++;
                }
                System.out.println(str + " 单词数: " + wordsCount);
            }
        }
    }
    
    Today is Monday
    Today is Monday 单词数: 3
    Today is  Monday
    Today is  Monday 单词数: 4
    Today is Monday?No!
    Today is Monday?No! 单词数: 3
    I`m OK.
    I`m OK. 单词数: 2
    
    // demo02
    Today is Monday
    Today is Monday 单词数: 3
    Today is  Monday
    Today is  Monday 单词数: 3
    Today is Monay?No!
    Today is Monay?No! 单词数: 4
    I`m Ok.
    I`m Ok. 单词数: 3
    
建议58:强烈建议使用UTF编码
  • 一个系统使用统一的编码

    // 使用该案例先手动调整编码格式,例如GBK,会乱码
    public class Suggest58 {
        public static void main(String[] args) throws UnsupportedEncodingException {
            String str = "编程日记";
            byte[] b = str.getBytes("UTF-8");
            System.out.println(new String(b));
        }
    }
    

    Java程序涉及的编码包括两部分:

    1. Java文件编码 : 记事本创建 .Java 后缀的文件, 文件的编码格式就是操作系统默认的格式 , 如果是 IDE工具创建的, 则依赖于 IDE 的设置。
    2. Class文件编码 : 通过 javac 命令生成的后缀名为 .class 的文件是 UTF-8 编码的 UNICODE 文件, 这在任何操作系统上都是一样的, 只要是 .class 文件就会是 UNICODE格式。
建议59:对字符串排序持一种宽容的心态
  • 如果排序不是一个关键算法,使用Collator类即可。主要针对于中文。

    public class Suggest59 {
        public static void main(String[] args) {
            String[] strs = {"张三(Z)","李四(L)","王五(W)"};
            demo01(strs);
            demo02(strs);
        }
    
        private static void demo02(String[] strs) {
            Arrays.sort(strs, Collator.getInstance(Locale.CHINA));
            int i = 0;
            System.out.println("=====demo02=====");
            for (String str : strs) {
                System.out.println((++i) + "、" + str);
            }
            System.out.println("=====demo02=====");
        }
    
        private static void demo01(String[] strs) {
            // 排序 默认升序
            Arrays.sort(strs);
            int i = 0;
            System.out.println("=====demo01=====");
            for (String str : strs) {
                System.out.println((++i) + "、" + str);
            }
            System.out.println("=====demo01=====");
        }
    }
    
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值