学习笔记之JavaSE(26)--JavaAPI详解1

今天学习的内容是String类


一、常用方法

String也就是字符串,关于字符串创建、String不变性、字符串常用操作(获取、转换等等)和intern()方法的知识以如下示例程序说明:

public class Test32 {
    public static void main(String[] args) throws UnsupportedEncodingException {
        //创建字符串
        String str_1 = "123";//由于"123"是字面量,它会在类首次加载时被放入运行时常量池
        String str_2 = new String("123");//此时运行时常量池之中已经有了一个"123",所以本行语句只会在堆上创建一个该字符串的拷贝对象
        String str_test = new String("abc");//此时运行时常量池里面并没有"abc",所以本行语句会先在常量池里面创建一个"abc",然后再在堆上创建一个拷贝字符串
        byte[] arr_1 = {65, 66, 67, 68, 69};
        char[] arr_2 = {65, 66, '3', 'q', 'r'};
        String str_3 = new String(arr_1);//ABCDE    字节数组 -->字符串
        String str_4 = new String(arr_1, 2, 3);//CDE
        String str_5 = new String(arr_2);//AB3qr    字符数组 -->字符串
        String str_6 = new String(arr_2, 1, 4);//B3qr
        System.out.println(str_3);
        System.out.println(str_4);
        System.out.println(str_5);
        System.out.println(str_6);
        System.out.println(str_1 + null);//123null  面试有可能出现

        /*
         * 实际上,如果希望使用运行时常量池中的字符串而不是堆上的,可以使用String的intern()方法
         * 当调用String类的intern()方法时,如果常量池中已经包括此字符串,则将其返回
         * 否则,将此字符串添加到运行时常量池中,并返回此字符串的引用
         */
        String ss = new String("kkk");//分别在常量池和堆创建"kkk",ss指向的是堆中的"kkk"
        String sss = ss.intern();//此时常量池中已经有"kkk"了,所以将"kkk"返回,sss指向的是常量池中的"kkk"
        System.out.println(ss == sss);//false
        System.out.println("xyz".intern());//xyz  此时常量池中没有"xyz",所以会将"xyz"添加到运行时常量池中,并将其返回

        /*
        String不变性:字符串一旦被初始化就不会被改变
        之所以字符串对象可以放进常量池,究其原因就是因为String具有不变性
        String类中每一个看起来会修改字符串值的API,实际上都是创建了一个新的字符串对象
         */
        String str_7 = "haha";
        String str_8 = str_7 + "!";//这实际上是新创建了一个字符串haha!,并赋给str_8引用

        //String常用操作1:获取
        String str = "32123123";
        int length = str.length();//获取字符串长度
        char ch = str.charAt(0);//获取指定索引的字符   字符串-->字符
        //!char c = str_1.charAt(10); StringIndexOutOfBoundsException  这是个RuntimeException
        int a = str.indexOf('2');//获取字符在字符串中的索引,如果包含此字符,返回其第一次出现时的索引
        int b = str.indexOf('4');//获取字符在字符串中的索引,如果不包含此字符,返回-1
        int c = str.indexOf('3', 1);//获取字符在字符串中的索引(从指定索引开始找),如果包含此字符,返回其第一次出现时的索引
        int d = str.indexOf("123");//获取字符串在字符串中的索引,如果包含此字符串,返回其首字符出现时的索引
        int e = str.indexOf("123", 3);//获取字符串在字符串中的索引(从指定索引开始找),如果包含此字符串,返回其首字符出现时的索引
        int a1 = str.lastIndexOf('1');//从后向前查找,获取字符在字符串中的索引,如果包含此字符,返回其第一次出现时的索引
        int b1 = str.lastIndexOf('4');//从后向前查找,获取字符在字符串中的索引,如果不包含此字符,返回-1
        int c1 = str.lastIndexOf('1', 3);//从后向前查找,获取字符在字符串中的索引(从指定索引开始找),如果包含此字符,返回其第一次出现时的索引
        int d1 = str.lastIndexOf("123");//从后向前查找,获取字符串在字符串中的索引,如果包含此字符串,返回其第一次出现时的索引
        int e1 = str.lastIndexOf("123", 3);//从后向前查找,获取字符串在字符串中的索引,如果包含此字符串,返回其第一次出现时的索引
        int x = str.indexOf("");//字符串前后都被空字符包起来了
        int y = str.lastIndexOf("");//字符串前后都被空字符包起来了
        String substr_1 = str.substring(2);//获取子字符串(指定起始索引)
        String substr_2 = str.substring(2, 4);//获取子字符串(指定起始索引和结束索引,不包括结束索引)
        System.out.println("length=" + length);
        System.out.println("ch=" + ch);
        System.out.println("a=" + a);
        System.out.println("b=" + b);
        System.out.println("c=" + c);
        System.out.println("d=" + d);
        System.out.println("e=" + e);
        System.out.println("a1=" + a1);
        System.out.println("b1=" + b1);
        System.out.println("c1=" + c1);
        System.out.println("d1=" + d1);
        System.out.println("e1=" + e1);
        System.out.println("x=" + x);
        System.out.println("y=" + y);
        System.out.println("substr_1=" + substr_1);
        System.out.println("substr_2=" + substr_2);

        //String常用操作2:转换
        String s = "哈哈,a,b,Sss";
        String[] arr_3 = s.split(",");//将字符串变成String数组(字符串的切割)
        char[] arr_4 = s.toCharArray();//将字符串变为字符数组   字符串-->字符数组
        byte[] arr_5 = s.getBytes();//将字符串变为字节数组     字符串-->字节数组
        String s1 = s.toUpperCase();//大写转换
        String s2 = s.toLowerCase();//小写转换
        String s3 = s.replace('s', 'a');//将字符串中的内容进行替换
        String s4 = s.replace('a', 'a');//将字符串中的内容进行替换
        String s5 = "   asd    ".trim();//将字符串两端的空白字符删除(如果用户输入的信息有空格,可以用此方法处理)
        String s6 = "abc".concat("123");//连接字符串(与+效果相同,建议用+)
        String s7 = String.valueOf(4) + 1;//将参数转变为字符串
        System.out.println(Arrays.toString(arr_3));
        System.out.println(Arrays.toString(arr_4));
        System.out.println(Arrays.toString(arr_5));
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);
        System.out.println(s4 == s);//true  如果没有发生替换,则返回原始的字符串
        System.out.println(s5);
        System.out.println(s6);
        System.out.println(s7);

        //String常用操作3:判断(重要)
        String m = "abc123abc";
        String n = "abc123ABC";
        System.out.println(m.equalsIgnoreCase(n));//判断验证码时需要这个方法
        System.out.println(m.equals(n));
        System.out.println(n.contains("abc"));
        System.out.println(n.startsWith("abc"));
        System.out.println(n.endsWith("ABC"));

        //String常用操作4:比较(从前往后按照Unicode值比较字符串的字符大小)
        System.out.println("abc".compareTo("abd"));
        System.out.println("abc".compareTo("abb"));
        System.out.println("abc".compareTo("abc"));

        /*
        * 练习:利用字符串与字符之间的转换,将字符串中的小写字母变换为大写字母
        */
        //第一种方式:使用charAt()和String构造函数
        String lower = "abcdef123~呵呵";
        char[] buf_1 = new char[lower.length()];
        for (int i = 0; i < lower.length(); i++) {
            char cha = lower.charAt(i);
            if (cha >= 'a' && ch <= 'z') {
                ch -= 32;
            }
            buf_1[i] = cha;
        }
        System.out.println(new String(buf_1));
        //第二种方式:使用toCharArray()和String构造函数
        char[] buf_2 = lower.toCharArray();
        for (int i = 0; i < buf_2.length; i++) {
            if (buf_2[i] >= 'a' && buf_2[i] <= 'z') {
                buf_2[i] -= 32;
            }
        }
        System.out.println(new String(buf_2));
    }
}

二、关于==操作的补充

之前说过以String s = "123";的形式创建字符串时,如果常量池中存在"123",s就会直接指向它。那么使用"+"操作符时会有变化吗?且看如下程序(面试要点):

public class Test48 {
	
	final static String ss1;      
	final static String ss2;  
	static {      
	     ss1 ="aaa";      
	     ss2 ="bbb";
	}  
	
	public static void main(String[] args){
		
		/*
		 * 使用“+”连接的两个字符串本身就是字面量时,如果池中存在这样连接后的字符串
		 * 则是不会重新创建字符串,而是直接引用池中的字符串;如果“+”连接的两字符串中只要
		 * 有一个不是字面常量串(即定义过的),是会产生新的字符串对象。
		 */
		 String str_1 = "aaa";    
		 String str_2 = "bbb";    
		 String str_3 = "aaabbb";    
		     
		 String str_4 = "aaa" + "bbb";//两个字面量直接相加在编译时就确定为aaabbb,不会产生新的字符串对象    
		 System.out.println(str_3 == str_4);//true
		     
		 str_4 = str_1 + "bbb";//会产生新的字符串对象    
		 System.out.println(str_3 == str_4);//false    
		     
		 str_4 = str_1 + str_2;//会产生新的字符串对象    
		 System.out.println(str_3 == str_4);//false 
		 
		 
		 /*
		  * 若在定义字符串变量时加final关键字修饰并且在声明时就赋予初始值
		  * 因为str1与str2都定义成了常量,在编译时就能确定,编译时就会将常量替换,等同于   
  		  *	str4 = "aaa"+"bbb",因此不产生新对象   
		  */
		 final String s1 = "aaa";    
		 final String s2 = "bbb";    
		 String s3 = "aaabbb";    
		 String s4 = s1 + s2;    
		 System.out.println(s3 == s4);//true  
		 
		 
		 /*
		  * 若在定义字符串变量时加static和final关键字修饰并且在静态代码块初始化
		  * 此时ss1与ss2相当于变量,因为静态代码块是在运行时才能确定,在编译时不能确定   
		  */
		   
		 String ss3 = "aaabbb";
		 String ss4 = ss1+ss2;
		 System.out.println(ss3==ss4);//false
	}
}

三、练习

1.字符串数组排序

public class StringTest1 {

	public static void main(String[] args) {

		// 给定一个字符串数组,按照Unicode表进行从大到小排序
		String[] arr = { "nba", "cba", "abc", "kk", "haha", "qq" };
		printArray(arr);//[nba, cba, abc, kk, haha, qq]
		sortString(arr);
		printArray(arr);//[abc, cba, haha, kk, nba, qq]
	}

	public static void sortString(String[] arr) {
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[i].compareTo(arr[j]) > 0) {
					swap(arr, i, j);
				}
			}
		}

	}

	public static void swap(String[] arr, int i, int j) {
		String temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}

	public static void printArray(String[] arr) {
		System.out.println(Arrays.toString(arr));
	}

}

2.获取子串在字符串中出现的次数

public class StringTest2 {

	public static void main(String[] args) {

		String str = "nbadwfdsnbadfnbadfnbaffnba";
		String key = "nba";

		int count = getKeyStringCount_1(str, key);
		System.out.println(count);// 5

		count = getKeyStringCount_2(str, key);
		System.out.println(count);// 5
	}

	public static int getKeyStringCount_2(String str, String key) {
		// 定义计数器
		int count = 0;

		// 定义变量记录key出现的位置
		int index = 0;

		while ((index = str.indexOf(key, index)) != -1) {
			index = key.length();
			count++;
		}

		return count;
	}

	public static int getKeyStringCount_1(String str, String key) {

		// 定义计数器
		int count = 0;

		// 定义变量记录key出现的位置
		int index = 0;

		while ((index = str.indexOf(key)) != -1) {
			str = str.substring(index + key.length());
			count++;
		}

		return count;
	}
}
3.获取两个字符串中最大相同子串

public class StringTest3 {

	public static void main(String[] args) {

		String str_1 = "sdkfjdslfhnbaklhdsf";
		String str_2 = "sloinbaih";
		String str = getMaxSubString(str_1, str_2);
		System.out.println(str);// nba
	}

	public static String getMaxSubString(String str_1, String str_2) {
		for (int i = 0; i < str_2.length(); i++) {
			for (int a = 0, b = str_2.length() - i; b != str_2.length() + 1; a++, b++) {
				String sub = str_2.substring(a, b);
				// System.out.println(sub);
				if (str_1.contains(sub)) {
					return sub;
				}
			}
		}
		return null;
	}
}
4.去除字符串两端空白(模拟trim()方法)

public class StringTest4 {

	public static void main(String[] args) {
		String s = "   nba   ";
		String str = myTrim(s);
		System.out.println(str);
	}

	public static String myTrim(String s) {

		int start = 0;
		int end = s.length() - 1;
		while (start <= end && s.charAt(start) == ' ') {
			start++;
		}
		while (start <= end && s.charAt(end) == ' ') {
			end--;
		}
		return s.substring(start, end + 1);
	}

}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值