美文网首页JavaSE 成长之路zijava学习
JavaSE基础(十二) - String 👾

JavaSE基础(十二) - String 👾

作者: SawyerZh | 来源:发表于2016-12-19 22:32 被阅读227次
    String 字符串.png

    今天学习了 Java 字符串的常用操作,写出来和简友们分享一下☺️
    还是老规矩,先上思维导图。

    1.String 概述

    一起读 API 📖
    public final class String extends Object
    implements Serializable, Comparable<String>, CharSequence
    The String class represents character strings. All string literals in Java programs, such as "abc", are implemented as instances of this class.

    通过查看 API 的概述我们可以知道以下几点:

    • String 是一个 final 修饰的类,不能被继承。
    • 字符串字面量值 "abc"也可以被看做是 String 对象。
    字符内存图1

    Reminder💁‍♂️:常量池中的值是不可被改变,但 String 对象是可以重指向的。


    2.String 构造方法

    • public String()
      空构造。

    • public String(byte[] bytes)
      字节数组 -> 字符串(使用平台默认字符集解码)

    一起读 API 📖
    Constructs a new String by decoding the specified array of bytes using the platform's default charset.

    • public String(byte bytes[], int offset, int length)
      将 byte 数组 从 offset 开始 转换 length 个。

    • public String(char value[])
      char 数组转换成字符串。

    • public String(char value[], int offset, int count)
      从数组中第 offset 开始转换,转换 count 个 char 为字符串。

    • public String(String original)
      将字符串常量 -> 字符串对象。


    3.String 面试题

    • 判断两个字符串地址值是否相等
      str1 和 str2 都存储在常量池,如果常量池中没有这个字符串对象,就创建一个,如果有就直接用;因为常量池中已经存在了 “abc”,所以 str2 直接使用,str1 与 str2指向了同一个对象,而 == 运算符比较的是两个对象的地址值,因此 str1 == str2。
    String str1 = "abc";
    String str2 = "abc";
    System.out.println(str1 == str2);   // true
    System.out.println(str1.equals(str2));  // true
    
    字符串内存图2
    • 下面这句话在内存中创建了几个对象?
      这段代码创建了两个对象,"abc" 存储在常量池中,new 的对象是存在堆内存中。
    String str1 = new String("abc");
    

    一起读 API 📖
    Initializes a newly created String object so that it represents the same sequence of characters as the argument; in other words, the newly created string is a copy of the argument string. Unless an explicit copy of original is needed, use of this constructor is unnecessary since Strings are immutable.

    • 判断定义为 String 类型的 str1 和 str2 是否相等?
      str1:指向堆内存对象的地址值。
      str2:指向常量池中的地址值。
    String str1 = new String(“abc”);
    String str2 = “abc”;
    System.out.println(str1 == str2);           // false
    System.out.println(str1.equals(str2));  // true
    
    • 判断定义为 String 类型的 str1 和 str2 是否相等?
      Java 中有常量优化机制,在编译时就将 str2 转换成了 “abc”,所以两个变量指向同一个常量池,内存地址值相同。
    String str1 = "a" + "b" + "c";
    String str2 = "abc";
    System.out.println(str1 == str2);           // true
    System.out.println(str1.equals(str2));  // true
    
    • 判断定义为 String 类型的 str2 和 str3 是否相等?
      字符串中 + 操作是通过 StringBuilderStringBuffer 以及 append 方法实现的,字符串转换是通过 toString 方法实现的。在堆内存和常量池中的地址都不同。
    String str1 = "ab";
    String str2 = "abc";
    String str3 = str1 + "c";
    System.out.println(str2 == str3);           // false
    System.out.println(str2.equals(str3));  // true
    
    字符串内存图3

    一起读 API 📖
    The Java language provides special support for the string concatenation operator ( + ), and for conversion of other objects to strings. String concatenation is implemented through the StringBuilder(or StringBuffer) class and its append method. String conversions are implemented through the method toString, defined by Object and inherited by all classes in Java.


    4.String 判断方法

    • public boolean equals(Object anObject)
      判断字符串是否相等。

    Reminder💁‍♂️:比较是会判断大小写的。

    • public boolean equalsIgnoreCase(String anotherString)
      忽略大小写,判断字符串是否相等。

    • boolean constans(String str)
      判断大字符串中是否包含小字符串。

    • boolean startsWith(String str)
      判断字符串中是否以某个指定的字符串开头。

    • boolean endsWith(String str)
      判断字符串中是否以某个指定的字符串结尾。

    • boolean isEmpty()
      判断字符串是否为空。

    Reminder💁‍♂️:如果 String == null 调用该方法会出现空指针异常


    5.Test👨‍💻模拟登录功能

    • 模拟登录:

      1. 用户每日有三次机会,如果输入错误,提示还剩几次。
      2. 用户名和密码都是 admin。
    public class String_Test1 {
    
        private static Scanner sc = new Scanner(System.in);
    
        private static final String USER_NAME = "admin";
    
        private static final String PASSWORD = "admin";
    
        private static final int CHANCE_TIMES = 3;
    
        public static void test() {
            for (int i = 0; i < CHANCE_TIMES; i++) {
                System.out.print("Please enter user name: ");
                String userName = sc.nextLine();
                System.out.print("Please enter password: ");
                String password = sc.nextLine();
                // 用字符串常量去做比较,防止字符串变量为 null。
                if (USER_NAME.equals(userName) && PASSWORD.equals(password)) {
                    System.out.println("Welcome " + userName + " login.");
                    break;
                } else {
                    // 今日试错次数用完,则给出提示。
                    if (i == CHANCE_TIMES - 1) {
                        System.out.println("Today chance use up, please tomorrow login.");
                        break;
                    }
                    // 给出错误提示,并输出今日剩余试错次数。
                    System.out.println("LoginFail: userName or password error.");
                    System.out.println("You has " + (CHANCE_TIMES - 1 - i) + " times.");
                }
            }
        }
    }
    

    6.String 获取方法

    • int length()
      获取字符串长度方法。

    Reminder💁‍♂️:我们的中文占 1 字符,转译符也占 1 字符。

    • char charAt(int index)
      获取指定索引位置的字符。

    Reminder💁‍♂️:StringIndexOutOfBoundsException 字符串索引越界异常

    • int indexOf(int ch)
      返回指定字符在字符串中第一次出现的索引

    Reminder💁‍♂️:
    可以传递 char 类型参数,因为会自动类型提升为 int
    如果不存在则返回 -1

    • int indexOf(String str)
      返回指定 字符串 在字符串中第一个字符出现的索引。

    Reminder💁‍♂️:
    如果不存在则返回 -1

    • int indexOf(int ch, int fromIndex)
      返回指定字符在此字符串中从指定索引开始第一次出现处的索引。

    Reminder💁‍♂️:包括当前索引 [fromIndex, ...]

    • int lastIndexOf(int ch, int fromIndex)
      从指定位置开始向前查找,返回第一次出现的索引

    • String substring(int start)
      从指定位置开始截取字符串,默认截取到末尾

    • String substring(int start, int end)
      返回字符串,从指定位置开始到指定位置结束截取字符串。

    Reminder💁‍♂️:[start, end) 左闭右开。


    7.String 遍历

    // 方式一
    String str = "Sawyer";
    for (int i = 0; i < str.length(); i++) {
        char ch = str.charAt(i);
        System.out.println(ch);
    }
    // 方式二
    char[] arr_char = str.toCharArray();
        for (int i = 0; i < arr_char.length; i++) {
        System.out.println(arr_char[i]);
    }
    

    8.Test👨‍💻统计不同字符类型的个数

    • 题目要求:统计一个字符串中(大写字母、小写字母、数字、其他字符)出现次数,其他字符出现次数。
    • 测试数据:ABCDEabcd123456!@#$%
    public static void test() {
    
        String str = "ABCDEabcd123456!@#$%";
    
        int lowerCaseCount = 0;
        int upperCaseCount = 0;
        int numberCount = 0;
        int otherCount = 0;
    
        for (int i = 0; i < str.length(); i++) {
            // String -> char[] 进行遍历
            char ch = str.charAt(i);
            if (ch >= 'a' && ch <= 'z') {
                lowerCaseCount++;
            } else if (ch >= 'A' && ch <= 'Z') {
                upperCaseCount++;
            } else if (ch >= '0' && ch <= '9') {
                numberCount++;
            } else {
                otherCount++;
            }
        }
    
        System.out.println("lowerCaseCount = " + lowerCaseCount + ", upperCaseCount = "
                + upperCaseCount + ", numberCount = " + numberCount +
                ", otherCount = " + otherCount + ".");
    }
    

    9.String 转换方法

    • public byte[] getBytes()
      通过 GBK 码表将字符串转换为字节数组。

    Reminder💁‍♂️:
    GBK 码表一个中文占用两个字节
    中文的第一个字节是负数

    • public char[] toCharArray()
      将字符串转换为字符数组。

    • static String valueOf(char[] chs)
      将字符串转换为字符数组。

    • public static String valueOf(int i)
      将 int 类型转换为字符串。

    Reminder💁‍♂️:
    通过重载方法,可以将任意类型转换为字符串。
    静态方法,底层是由 String 类的构造方法完成的。

    • public String toLowerCase()
      字符串小写转换,返回字符串

    • public String toUpperCase()
      字符串大写转换,返回字符串。

    • public String concat(String str)
      字符串拼接,返回字符串。

    Reminder💁‍♂️:
    concat :只能对两个 String 做拼接操作。
    + :使用的更广泛。


    10.String 其他方法

    • public String replace(char oldChar, char newChar)
      字符替换。

    Reminder💁‍♂️:如果 oldChar 不存在,则保留原字符不改变。

    • public String replace(CharSequence target, CharSequence replacement)
      字符串替换。

    • public String trim()
      去除字符串两侧的空格,返回新字符串。

    • public int compareTo(String anotherString)
      按字符逐个比较两个字符串 unicode 码表值,如果长度相等,只返回第一个不同字符 unicode 对应的差值;如果长度不等则 length 相减。

    String str1 = "abc";
    String str2 = "abcd";
    int str_compare = str1.compareTo(str2);
    System.out.println(str_compare);        // -1
    

    11.Test👨‍💻String关键字检索

    • 题目要求:
      1.在 source 字符串中检索 target 关键字出现的次数。
      2.将 target 关键字在字符串中用 "[ ]" 标记。
    public class String_Test8 {
    
        public static void test() {
            String source = "woailuchen,luchenbutongyuyaoyanhuo," +
                    "wulunluchenhaishiyaoyanhuo,liaodelaidejiushihaobaobao";
            String target = "luchen";
    
            int count = targetCount(source, target);
            System.out.println(count);
            String mark_str = markStringAccordingTraget(source, target);
            System.out.println(mark_str);
        }
    
        // 获取检索关键字出现次数
        private static int targetCount(String source, String target) {
            int targetCount = 0;
            {
                // 从targetOffset关键字处开始检索
                int targetOffset = 0;
                while (true) {
                    int targetIndex = source.indexOf(target, targetOffset);
                    if (targetIndex == -1) {
                        break;
                    } else {
                        // 改变将检索开始的fromindex
                        targetOffset = targetIndex + target.length();
                        targetCount++;
                    }
                }
            }
            return targetCount;
        }
    
        // 将关键字用 "[]" 标记
        private static String markStringAccordingTraget(String source, String target) {
            return source.replace(target, " [ " + target + " ] " +
                    "");
        }
    }
    

    悄悄话 🌈

    • 这是我个人发表的第 3 篇简书 Blog,靠着大家的鼓励我会继续抽时间继续和大家分享我在 JavaSE 的学习中的一点心得,也希望读者们多多批评指教,多多支持。
    • 每篇文章最开心的地方就是在这里和大家分享一点我个人最近的情况,最近每天都睡的很晚,大概每天保持 5 小时的睡眠的样子,因为明天放假一天,所以抽时间写了这篇总结。
    • 之前做 iOS 开发,来简书中每次都能找到满意的答案,也看了很多大牛们,不光是技术能力强,技术的表述能力也是一流。现在轮到我自己从 Java 小白开始学习了,我知道也许会有很多人在现阶段和我一样需要有人帮助解答问题,我认为我除了自己的学习总结之外还可以做的更多,每次收到文章的点赞我都深深的感觉到自己做了一件很有意义的事情。
    • 后面的学习可能需要用到更多的代码示例,在文章中引用代码块的方式可能不太合适了,我会将项目放在 GitHub 上,并且在文章中附上链接,小伙伴们到时要记得光顾哟!🤡

    彩蛋 🐣

    • 最近开通了简书专题 JavaSE 成长之路,主要为一样正在 JavaSE 修行中的简友们提供了技术交流的平台,希望大家多多投稿交流互动。

    相关文章

      网友评论

      • Vincentl_Hui:SawyerZh: 你在悄悄话中提到你以前是IOS开发的,我想问一下你目前是从事后端开发吗?
        SawyerZh:@Vincentl先生 前端的开发精雕细琢的感觉我很喜欢,可能是大学也学习了其他的计算机知识,对后端的开发也一直有探索欲望,就自己倒腾着一直在学习,正好有机会就转到了后端开发上了。
        Vincentl_Hui:@SawyerZh 其实我更想知道IOS开发前景挺不错的,为何选择了后端开发呐?
        .
        SawyerZh:@Vincentl先生 对的

      本文标题:JavaSE基础(十二) - String 👾

      本文链接:https://www.haomeiwen.com/subject/pnqtvttx.html