String --- 代表字符串的类, 是一个最终类,不能被继承,没有子类。所有的字符串都是他的对象 。
字符串是一个常量,定义之后存储在运行时常量池中且只存储一份,定义好之后不可改变,一样字符串是被共享的(同样 的字符串地址相同)。
String s1 = "ab" // 在常量池中创建一个"ab"对象,s1 指向"ab"在常量池中的地址
String s2 = new Strin("ab"); //此过程产生两个对象 ; 通过new关键字现在堆内存中开辟一块空间存放"ab"在常量池中的内存地址。
String s3 = "a" + "b"; //此时"a" 和"b" 是两个字面量(一般的整数、小数、字符串常量)在运算,JVM在编译时会对这个运算进行优化 String s3 = "ab";
String s4 = "a"; s4 +="b"; // 此过程产生了5个对象 ,在底层调用了StringBuilder的append()方法,底层实现 s4 = new StringBuilder("a").append("b").toString();,其中toString()方法底层 是 new String(), 执行完成之后s4指向了一个新的地址。
所以: s1 = s2; //false s1 = s3; //true s1 = s4; //false s2 = s3;//false s2 = s4; //false s3 = s4;//false
StringBuilder | StringBuffer 两个类中的方法一模一样 但是StirngBuilder是线程不安全的 ,StringBuffer是线程安全的。
建议: "+" 和 append()拼接字符串 : "+"拼接时 每次拼接多产生3个对象 append() 每次拼接时多产生1个对象 , 所以append拼接字符串的效率在空间和时间上都要远高于"+"。 所以拼接多个字符串建议使用StringBuilder 。
常用方法摘要:
1.charAt() 获取指定下标上的字符
2.length() 获取字符串的长度
练习: 1. 从控制台输入一个字符串,判断是否是回文
2. 输入一个字符串,统计这个字符串中字母、数字、即符号的个数
3. 输入一个字符串,提取里面的数字并求和
4. 驶入一个字符串,提取数字并排序
5. 驶入一个字符串,记录每个元素出现的次数
public class Demo_01 {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("请输入一个字符串");
String ss = s.nextLine();
s.close();
isHuiwen(ss);
printNum(ss);
printSum(ss);
printSortNum(ss);
}
/**
* 判断一个字符串是不是回文
* */
public static void isHuiwen(String str ){
for(int i=0;i<str.length()/2;i++){
if(str.charAt(i) != str.charAt(str.length()-1-i)){
System.out.println("不是回文!");
return;
}
}
System.out.println("是回文");
}
/**
* 统计字符串中数字、字母、其他字符的个数
* */
public static void printNum(String str ){
int a = 0,b = 0,c = 0,d = 0;
char[] cc = str.toCharArray();
for(int i = 0;i<str.length();i++){
if(cc[i]>=48&&cc[i]<=58){
a++;
}else if(cc[i]>=65&&cc[i]<=(65+26)){
b++;
}else if(cc[i]>=97&&cc[i]<=(97+26)){
c++;
}else{
d++;
}
}
System.out.println("数字的个数:"+a);
System.out.println("大写字母的个数:"+b);
System.out.println("小写字母的个数:"+c);
System.out.println("其他字符的个数:"+d);
}
/**
* 提取字符串中数字并求和
* */
public static void printSum(String str){
int a = 0,b = 0;
char[] cc = str.toCharArray();
for(int i = 0;i<str.length();i++){
if(cc[i]>=48&&cc[i]<=58){
a+=cc[i]-48;
}
}
System.out.println("字符串中数字的和:"+a);
}
/**
* 提取字符串例的数字并排序
* */
public static void printSortNum(String str){
int a = 0,b = 0;
char[] cc = str.toCharArray();
List<Integer> list = new ArrayList<Integer>();
for(int i = 0;i<str.length();i++){
if(cc[i]>=48&&cc[i]<=58){
a=cc[i]-48;
list.add(a);
}
}
int[] iii = new int[list.size()];
for(int i = 0;i<list.size() ; i++){
iii[i] = list.get(i);
}
Arrays.sort(iii);
System.out.println("字符串中数字排序后的数组:"+Arrays.toString(iii));
}
/**
* 记录字符串中每个元素出现的个数
* */
public static void printYuansuNum(String str){
int count = 1;
char[] cc = str.toCharArray();
Arrays.sort(cc);
System.out.println(cc);
for(int i=0;i<cc.length-1;i++ ){
if(cc[i]==cc[i+1]){
count ++;
}else{
//输出的是上一次比对的结果
System.out.print(cc[i]+"出现了"+count+"次 ; ");
count = 1;
}
}
//输出最后一次比对的结果
System.out.print(cc[cc.length-1]+"出现了"+count+"次 ; ");
}
/**
* 记录字符串中每个元素出现的个数
* */
public static void printYuansuNum2(String str){
char[] bs = str.toCharArray();
boolean[] bls = new boolean[bs.length];
int count = 1;
for(int i = 0;i<bs.length;i++){
if(!bls[i]){
bls[i] = true;
for(int j = i+1;j<bs.length;j++){
if(bs[i] == bs[j]){
count++;
bls[j] = true;
}
}
System.out.println(bs[i]+"出现了"+count+"次;");
count = 1;
}
}
}
}
3.comperTo() 按字典顺序比较字符串 ,
底层实现: 1. 会把两个字符串转化为字符数组2.按位相减3.如果差不是0,则直接返回;如果差是0,下一位继续相减4.如果每一位相减都为0,并且一个字符串首先遍历完了,返回对象字符串与参数字符串的长度之差
结果: 0:这俩字符串一致,正数:对象字符串比较大 ,反之参数字符串比较大
4.ComperToIgnoreCase() 忽略大小写比较。
5.contact() 将指定字符串拼接到对象字符串后。
底层实现: 1. 将两个字符串转化为字符数组str.toCharArray() 2.将两个字符数组进行合并System.arrayCopy() 3.将合并后数组转换为字符串String str = new String(char[]);
6.String( char[] ,offset , count); 要转换的数组,偏移量(要开始转换的起始下标),转化的字符个数
7.contians() 判断字符串中是否包含指定的参数。返回true|false。
8.endsWith() 判断次字符串是否是指定字符串结尾。
9.equals() 判断两个字符串值是否相等。底层重写了Object的equals方法
10.equalsIgnoreCase() 不考虑大小写比较字符串
toLowerCase() | toHeigherCase() 将所有字符转为小 |大写
getBytes(编码) 将字符串转换为字节数组。
编码:将不同的字符对应不同的数字
码表:ISO-8859-1 西欧码表 一个字符存储一个字节
GB2312 -->GBK 规定一个字符占两个字节 中国标准码表 收录了常见的基本的简体汉字,以及一部分常见的繁体汉字
Unicode 编码体系 包含utf-8 utf-8规定一个字符占3个字节
所有的码表默认兼容西欧编码 --- 无论哪个码表中,英文一个字符永远占一个字节。
当没有指定编码的时候,会默认使用系统平台码。
windows默认GBK linux默认utf-8
11.String(byte[],编码); 将字节数组按照指定编码转换为字符串
12.String(byte[] ,begin,count,编码); 将字节数组从begin位按照指定编码转换count个字节为字符串
练习: 1. 输入一个字符串和数字,这数字表示字节个数,根据指定的字节个数,截取指定的字符串(不能出现半个字符)
/**
* 输入一个字符串和数字,这数字表示字节个数,根据指定的字节个数,
* 截取指定的字符串(不能出现半个字符)
* */
public static void print1(){
Scanner s = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = s.nextLine();
System.out.println("请输入一个数字:");
int num = s.nextInt();
s.close();
byte[] bs = str.getBytes();
String str2 = new String(bs ,0 ,num );
if(str2.charAt(str2.length()-1) != str.charAt(str2.length()-1)){
str2 = new String(bs,0,num-1);
}
System.out.println(str2);
}
13.hashCode() String中的hashCode()做过重写---同一个字符串无论是在什么情况下(设备、环境),哈希吗一定一致---保证字符串的唯一性。返回的字符串在常量池中的地址,而不是对象在堆中的地址。
14.isEmpty() 判断字符串是不是一个空串 (判断长度为0)
注意: null身上没有任何的方法和属性,只要用null区调用方法或属性一定会出空指针异常。
15.indexOf(int ch) :获取指定字符字字符串中第一次出现的下标。找不到则返回-1;找到则返回对应位置。
16. indexOf(int ch,int fromIndex) : 获取指定字符在字符串中从fromInde位置开始第一次出现的下标
练习:获取指定字符在字符串中出现的所有位置。
/**
* 输入一个字符串,获取这个字符在字符串中出现的的所有位置。
* */
public static void getIndexs(String str,String s){
int index = -1;
for(int i=0;i<str.length();i++){
index = str.indexOf(s,i);
if(index>=0){
System.out.print(index+" ");
i = index;
}
}
}
17. lastIndexOf(int ch) :获取指定字符在字符串中最后一次出现的位置。
18. lastIndexOf(int ch ,int fromIndex) : 获取指定字符在字符串中指定位置之前(不包含)最后一次出现的位置。
19. replace(str,str) : 以第二个参数替换字符串中第一个参数的字符。
20. startWith(str) : 判断字符串是否以指定字符串开头。
21. subString(beginIndex , endIndex) : 按照指定的范围截取字符串 (含左不含右)
22. trim() : 去掉头部和尾部的空白字符。
23. valueOf(arg): 将参数转换为字符串格式。 底层实现:在打印对象时,调用其对象的toString() ;但是字符数组是转换为一个字符串显示。
StringBuilder | StringBuffer
这两个类中的属性和方法几乎一致,stringBuilder是线程不安全的;StringBuffer是线程安全的。
1.append(str) : 拼接字符串。
2. revese(); 反转字符串。
3. spilt(ch) : 以指定字符切割字符串。