文章目录
- 一、字符串的定义方式
- 二、String注意问题
- 三、内存分布(注意问题详解)
-
- 四、练习问题
-
- 五、字符串不可变
-
- 六、StringBuilder和StringBuffer
- StringBuilder
- StringBuffer
- String和StringBilder、StringBuffer区别
- 类型的转换
- 七、字符(char)、字节(byte)、字符串(string)
-
- 八、字符串比较
- 九、字符串查找
- 1.contains
- 2.indexOf
- 3.lastIndexOf
- 4.startsWith
- 5.endsWith
- 十、字符串替换
-
- 十一、字符串的拆分
- 十二、字符串截取
- 十三、其他方法
- 十四、练习
一、字符串的定义方式
public static void main(String[] args) {
String str = "hello";
String str1 = new String("hello");
char[] array = {'a','b','c','d'};
String str2 = new String(array);
String str3 = new String(array,2,2);
}
二、String注意问题
public static void main(String[] args) {
String str = "hello";
String str1 = new String("hello");
System.out.println(str == str1);
String str2 = "he" + new String("llo");
System.out.println(str == str2);
String str3 = "he" + "llo";
System.out.println(str == str3);
String str4 = "he";
String str5 = str4 + "llo";
System.out.println(str5 == str);
}
小问题:以下str1和str2的区别
String str1 = null;
String str2 = "";
str1没有指向任何对象
str2指向了一个对象,这个对象中没有任何的内容。
三、内存分布(注意问题详解)
1、分布方式1
String str = "hello";
String str1 = new String("hello");
System.out.println(str == str1);
因str为局部变量,str在栈上开辟内存指向的对象hello则会在常量池中存储。
str1也是局部变量,str1也在栈上开辟内存而new的对象则在堆上开辟内存,一个在常量池,一个在堆上,指向的对象不同所以返回false。
在new时,会在源码中有这样的两种语句。
this.value是当前String的value,查看value
会发现是一个char类型的数组类型(引用)
也就是说你new的时候会在引用中存在一个value[] (数组引用)
在这个数组中存储的是original.value(参数的地址),这个参数的地址是常量池中的hello的地址(语句一中直接赋值的hello的地址)。
2、分布方式2
String str2 = "he" + new String("llo");
System.out.println(str == str2);
在str2中的he在常量池中建立对象,new在堆上建立对象这个对象中存了一个常量池中的“llo”(因常量池中没有这个值),所以会新建一个llo值。这两个值拼接在堆上创建一个对象是hello所以返回的还是false。
3.分布方式3
String str3 = "he" + "llo";
System.out.println(str == str3);
String str4 = "he";
String str5 = str4 + "llo";
System.out.println(str5 == str);
str3中he和llo都是常量,所以在编译时就把他直接拼装了放到了常量池中,所以str和str3相等。
str5不相等的原因是str4是一个变量,在编译时不能进行组合。
常量池
同样的字符串只能存放一个,如果有返回现在的地址给引用,如果没有,存放进去,返回地址给引用
池的作用:节省资源。
四、练习问题
问题一:
public static void change(String str , char[] array){
str = "hello word";
array[0] = 'g';
}
public static void main(String[] args) {
String str = "hello";
char[] array = {'a','b','c','d'};
System.out.println(str);
System.out.println(array);
change(str,array);
System.out.println(str);
System.out.println(array);
}
其中str是传值,而array是传址,str开始在常量池中创建一个hello对象,保存了地址,传过去后又在常量池上创建了hello word,形参保存用来保存这个值,而实参则不会进行改变。
问题二:
在上面代码中知道了以下代码返回的是false
public static void main(String[] args) {
String str = "hello";
String str1 = new String("hello").intern();
System.out.println(str == str1);
}
此时返回true的原因是,.intern()会先查看常量池中是否有相同的常量,如果有返回这个常量,如果没有那么新建一个,intern()叫做入池。
五、字符串不可变
public static void main(String[] args) {
String str = "hello";
str = str+"word";
str = str+"hello1";
System.out.println(str);
}
在这个过程中产生了大量的临时对象,常量池上产生了:hello、word、hello1
堆上产生helloword、hellowordhello1。字符串的拼接不是在原有的基础上进行相加而是产生一个新的对象后进行返回。
public static void main(String[] args) {
String str = "hello";
str = str+"word";
}
更改String
要想更改那就需要使用到反射
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
String str = "abc";
Class cl = String.class;
Field valueField = cl.getDeclaredField("value");
valueField.setAccessible(true);
char[] value = (char[])valueField.get(str);
value[0] = 'h';
System.out.println(str);
}
六、StringBuilder和StringBuffer
StringBuilder
stringBuilder的使用
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("ab");
stringBuilder.append("cd");
System.out.println(stringBuilder);
}
StringBuffer
StringBuffer的使用
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("hello");
System.out.println(stringBuffer);
}
String和StringBilder、StringBuffer区别
public static void main(String[] args) {
String str = "abc";
String str1 = "def";
String str2 = str + str1;
System.out.println(str2);
}
在以上代码中会进行大量对象,而编译器在进行编译的时候会进行优化
public static void main(String[] args) {
String str = "abc";
String str1 = "def";
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(str);
stringBuilder.append(str1);
String str2 = stringBuilder.toString();
System.out.println(str2);
}
区别:
- String的拼接会产生新的对象,但是StringBuilder和StringBuffer使用append方法进行拼接,返回的是当前对象。
- String的拼接会被优化成StringBuilder
- stringbuilder和stringBuffer
由上面两张图可以发现StringBuilder比StringBuffer多了一个 synchronized 这个是用来保证线程安全的,所以说在单线程时使用StringBuilder而多线程中使用StringBuffer
类型的转换
String类型转换成StringBuilder(StingBuffer相同)
public static void main(String[] args) {
String str1 = "abc";
StringBuilder sb = new StringBuilder(str1);
System.out.println(sb);
StringBuilder sb2 = new StringBuilder();
sb2.append(str1);
System.out.println(sb2);
}
StringBuilder转换成String
使用toSting方法
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("add");
String append1 = stringBuilder.toString();
System.out.println(append1);
}
面试题:String与StringBuilder、StringBuffer的区别
- String的内容不可修改,StringBuilder与StringBuffer的内容可以修改
- StringBuilder与StringBuffer大部分功能相似
- StringBuffer采用同步处理,属于线程安全操作;而StringBuilder采用异步处理,属于线程不安全操作。
七、字符(char)、字节(byte)、字符串(string)
1.字符串与字符之间的转换
public static void main(String[] args) {
String str = "abcd";
char str1 = str.charAt(2);
System.out.println(str1);
char[] str2 = str.toCharArray();
System.out.println(str2);
}
以上两种方式一种是变换称为char类型,一种是变换成为char类型的数组。
小练习:判断字符传中是否全部为数字
public static void main(String[] args) {
String str = "01234a67";
for (int i = 0; i < str.length(); i++) {
char str1 = str.charAt(i);
if('0' < str1 && str1 > '9'){
System.out.println("不都是数字字符");
return;
}
}
System.out.println("此字符串中全部为数字");
}
2.字节与字符串
字节转字符串
public static void main(String[] args) {
byte[] bytes = {97,98,99,100};
String str = new String(bytes);
System.out.println(str);
}
带有两个参数时,以下代表意思
是从第一个参数开始往后偏移两个单位。
public static void main(String[] args) {
byte[] bytes = {97,98,99,100};
String str = new String(bytes,1,2);
System.out.println(str);
}
字符串转字节
public static void main(String[] args) {
byte[] bytes = {97,98,99,100};
String str = new String(bytes,1,2);
System.out.println(str);
byte[] bytes1 = str.getBytes();
System.out.println(Arrays.toString(bytes));
}
编码转换处理
public static void main(String[] args) throws UnsupportedEncodingException {
String str1 = "abcd";
String str2 = "小明";
byte[] bytes1 = str1.getBytes("GBK");
byte[] bytes2 = str2.getBytes("utf-8");
System.out.println(Arrays.toString(bytes1));
System.out.println(Arrays.toString(bytes2));
}
不同的编码格式有不同的
八、字符串比较
public static void main(String[] args) {
String str1 = "abc";
String str2 = "ABC";
System.out.println(str1.equals(str2));
System.out.println(str1.equalsIgnoreCase(str2));
System.out.println(str1.compareTo(str2));
}
以上是三种比较方式
- equals为比较字符串是否相等
- equalsIgnoreCase为忽略大小写比较字符串是否相等
- compareTo为比较字符串返回一个值
例题:检查两个字符串是否相等
OJ链接
class Solution {
public boolean arrayStringsAreEqual(String[] word1, String[] word2) {
String str1 = "";
for (int i = 0; i < word1.length; i++) {
str1 += word1[i];
}
String str2 = "";
for (int i = 0; i < word2.length; i++) {
str2 += word2[i];
}
return str1.equals(str2);
}
}
思路就是:先拼装起来后进行比较。
优化后
class Solution {
public boolean arrayStringsAreEqual(String[] word1, String[] word2) {
StringBuilder sb = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < word1.length; i++) {
sb.append(word1[i]);
}
for (int i = 0; i < word2.length; i++) {
sb2.append(word2[i]);
}
return (sb.toString()).equals(sb2.toString());
}
}
使用StringBuilder来进行操作。
九、字符串查找
1.contains
判断是否有包含相同的字符串
public static void main(String[] args) {
String str1 = "abcdefg";
System.out.println(str1.contains("def"));
}
2.indexOf
在主字符串中查找子字符串的位置。
public static void main(String[] args) {
String str1 = "abcdefg";
System.out.println(str1.indexOf("abc"));
}
自己书写有两种算法
1.BF算法(朴素算法)
2.KMP算法
两个参数:
public static void main(String[] args) {
String str1 = "abcdefg";
System.out.println(str1.indexOf("abc",6));
}
3.lastIndexOf
从后往前找你所需要的字符串
public static void main(String[] args) {
String str1 = "abcabcabcabcabc";
System.out.println(str1.indexOf("abc",6));
System.out.println(str1.lastIndexOf("abc",6));
}
4.startsWith
判断一个字符串是否是以规定字符串开始
public static void main(String[] args) {
String str1 = "abcabcabcabcabc";
System.out.println(str1.startsWith("abc"));
System.out.println(str1.startsWith("abc",5));
}
5.endsWith
判断一个字符串是否以规定字符串结尾。
public static void main(String[] args) {
String str1 = "abcabcabcabcabc";
System.out.println(str1.endsWith("abc"));
}
十、字符串替换
1.replace
两个参数第一个参数是源字符串,第二个参数是要修改的字符串
可以是字符类型,也可以是字符串类型
public static void main(String[] args) {
String str1 = "abcabcabcabcabc";
System.out.println(str1);
String str2 = str1.replace('a','b');
System.out.println(str2);
String str3 = str1.replace("abc","ABC");
System.out.println(str3);
}
2.replaceAll
比起上面可以传字符类型,这个方法默认就是字符串类型
public static void main(String[] args) {
String str1 = "abcabcabcabcabc";
System.out.println(str1);
String str3 = str1.replaceAll("abc","ABC");
System.out.println(str3);
}
十一、字符串的拆分
public static void main(String[] args) {
String str1 = "abc&def&hig";
String[] str2 = str1.split("&");
for (String s:str2) {
System.out.println(s);
}
}
有一些特殊的字符需要进行转义比如 . 转义时需要注意使用\时在字符串中需要对\进行转义。
public static void main(String[] args) {
String str1 = "192.168.1.10";
String[] str2 = str1.split("\\.");
for (String s:str2) {
System.out.println(s);
}
}
加了一个参数代表着分成几组。
public static void main(String[] args) {
String str1 = "192.168.1.10";
String[] str2 = str1.split("\\.",2);
for (String s:str2) {
System.out.println(s);
}
}
若有多个分割符那么可以使用 | 来进行分割
public static void main(String[] args) {
String str1 = "192-168^1$10";
String[] str2 = str1.split("-|^|$");
for (String s:str2) {
System.out.println(s);
}
小练习
第一次根据=分割,第二次根据&进行分割
public static void main(String[] args) {
String s1 = "abc&456=def&789";
String[] strings = s1.split("=");
for (String s:strings) {
String[] strings1 = s.split("&");
for (String s2:strings1) {
System.out.println(s2);
}
}
}
十二、字符串截取
使用substring的时候,后面参数代表从哪里开始截取,之后的所有字符都被获取到了
public static void main(String[] args) {
String str = "abcdefg";
String str1 = str.substring(2);
System.out.println(str1);
}
两个参数的时候第一个参数代表开始,第二个参数代表结束(左闭右开)。
public static void main(String[] args) {
String str = "abcdefg";
String str1 = str.substring(2,5);
System.out.println(str1);
}
十三、其他方法
1.trim()
public static void main(String[] args) {
String str = " str 123 ";
System.out.println(str.trim());
}
2.toUpperCase与toLowerCase
public static void main(String[] args) {
String strings = "abcdrf";
System.out.println(strings.toUpperCase());
String string = "ABCDEF";
System.out.println(string.toLowerCase());
}
3.intern
public static void main(String[] args) {
String str = "hello";
String str1 = new String("hello").intern();
}
4.concat
public static void main(String[] args) {
String str1 = "ab";
String str2 = "cd";
System.out.println(str1.concat(str2));
}
5.isEMpty
判断是否是空字符串。
public static void main(String[] args) {
String str1 = "";
String str2 = null;
System.out.println(str1.isEmpty());
System.out.println(str2.isEmpty());
}
十四、练习
逆至字符串
public static String reverse(String str) {
if(str == null)return null;
if(str.equals(""))return str;
char[] str1 = str.toCharArray();
int i = 0;
int j = str1.length-1;
while (i < j) {
char tmp = str1[i];
str1[i] = str1[j];
str1[j] = tmp;
i++;
j--;
}
return String.valueOf(str1);
}
public static void main(String[] args) {
String str = "abcdef";
String ret = reverse(str);
System.out.println(ret);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)