String字符串介绍
String字符串
String类使我们使用频率非常高的一个类.无论是在工作还是学习中,String类不仅可以快速的处理字符串类型,也可以作为其他类型的转换中介,
String内部使用 char[] value数组进行实现的,并且使用final关键字限制其内容不能被修改.
这样做得优势有:
a)方便的放到池中
b) hashCode也不可变
c)线程安全更有保证.
在java.lang这个包中的,但是使用这个包里的内容不需要自己手动导入
一 字符串内容相等比较方法辨析
对于String类型,如果要比较两个String对象内容是否相等
不能直接使用 ‘’ 来进行比较.因为 '’ 在实质上是直接比较两个对象所引用的地址值.而不是比较实际对象的内容.所以我们需要使用.equals方法进行比较
但是因为创建字符串的方法有差异,需要字符串常量池的影响
如果字符串被放入字符串常量池,在编译的过程中会优先进行比较,如果常量池中存在,就让引用指向这个值,而不会重新创建。因此在使用==进行比较地址的时候是相同的。
String s1 = new String("abc");
String s2 = new String("abc");
//String s2 = new String("abc").intern();
//使用.intern方法将abc加入字符串常量池,
String s3 = "abc";
String s4 = "abc";
if (s1.equals(s2)) {
System.out.println("可以使用 equals 来比较");
} else {
System.out.println("不可以使用 equals 来比较");
}
if (s1 == s2) {
System.out.println("可以使用== 来比较");
} else {
System.out.println("不可以使用== 来比较");
}
System.out.println("============================");
if (s3.equals(s4)) {
System.out.println("可以使用 equals 来比较");
} else {
System.out.println("不可以使用 equals 来比较");
}
if (s3 == s4) {
System.out.println("可以使用== 来比较");
} else {
System.out.println("不可以使用== 来比较");
}
System.out.println("============================");
if (s2.equals(s3)) {
System.out.println("可以使用 equals 来比较");
} else {
System.out.println("不可以使用 equals 来比较");
}
if (s2 == s3) {
System.out.println("可以使用== 来比较");
} else {
System.out.println("不可以使用== 来比较");
}
运行结果:
加入.intern()方法后 未加入
从结果我们可以看出,在使用new关键字创建字符串对象时,不会查询字符串常量池,而是直接创建一个对象,所以s1 s2两者引用的地址不相同,在使用了.intern()方法之后将S2和S3进行比较,从不可以使用 == 比较变成了可以使用此时S2和S3引用的是同一个值.
二 字符串常用方法:
intern方法
将字符串对象加入到字符串常量池中.
字符与字符串转换:
方法名 | 描述 |
---|---|
public String(char value[]) | 将字符数组中的内容变为字符串 |
public String(char value[],int offset,int count) : | 将部分字符数组中的内容变为字符串. |
public char charAr(int index) | 取得指定位置的字符,索引从0开始 |
public char[] tocharArray() | 将字符串变为字符数组, |
字节与字符串
方法名 | 描述 |
---|---|
public String(byte bytes[]) | 将字节数组中的内容变为字符串 |
public String(char bytes[],int offset,int length) : | 将部分字符数组中的内容变为字符串. |
public byte[] get Bytes(Sting str) | 将字符串与字节数组的形式返回 |
public byte[] getBytes(String charsetName)throwUnsupportedEncodingException | 编码转换处理 |
字符串比较
方法名 | 描述 |
---|---|
public boglean. equal s(Object anQbject) | 区分大小写的比较 |
public boglean equalsIgnoreCase(String anotherstring) | 不区分大小写的比较 |
public int compareTo(String anotherString) | 比较两个字符串大小关系 |
public boglean. equal s(Object anQbject)
比较字符串内容是否相等
String str = new String("Hello");
//方式一
System.out.println(str.equals("Hello"));
//方式二
System.out.println("Hello".equals(str));
在使用时尽量使用方式二,因为如果str为null,在运行的时候,方式一的代码会抛出异常,
public int compareTo(String anotherString)
在String类中compareTo(方法是一个非常重要的方法,该方法返回-个整型,该数据会根据大小关返回三类内容:
- 相等:返回0.
- 小于:返回内容小于0.
- 大于:返回内容大于0
System.out.println(“A”.compareTo(“a”)); // -32
System.out.println(“a”.compareTo(“A”)); // 32
System.out.println(“A”.compareTo(“A”)); // 0
System.out.println(“AB”.compareTo(“AC”))//-1
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
可以看出compareTo是通过字典序比较的并且返回不相同处的编码差值.
字符串查找
方法名 | 描述 |
---|---|
public . boolean contains(CharSequence s) | 判断一个子字符串是否存在 |
public int index0f(String str) | 从头查找指定字符串的位置,如果查到了返回位置的,所以查不到返回-1 |
public . int . index0f(Strin str, .int. fromIndex) | 从指定位置开始查找子字符串的位置 |
public .int lastIndexOf(String str) | 从后往前查找子字符串的问题 |
public . int. lastIndex0f(String str, int. fromIndex) | 从指定位置往前查找, |
public .boolean startsWith(String.prefix) | 判断是否以指定字符串开头 |
public boolea startsWith(String prefix, int toffset) | 从指定位置开始判断是否以指定字符串开头, |
public . boolea endsWith(String . suffix) | 判断是否已指定字符串结尾, |
String str = "helloworld" ;
System.out.println(str.indexOf("l")); // 2
System.out.println(str.indexOf("l",5)); // 8
System.out.println(str.lastIndexOf("l")); // 8
String str1 = "**@@helloworld!!" ;
System.out.println(str1.startsWith("**")); // true
System.out.println(str1.startsWith("@@",2)); // ture
System.out.println(str1.endsWith("!!")); // true
字符串拆分
方法名 | 描述 |
---|---|
public .String[ . split(String regex) | 以regex为分割拆分 |
public.String[] . split(String regex, int.limit) | 以regex为分割拆分,用limit控制返回的String数组的最大长度 |
1.字符"I","*","+“都得加上转义字符,前面加上”\".
2.而如果是"\",那么就得写成"\\".
3.如果一个字符串中有多个分隔符,可以用"I"作为连字符.
String s = "192a168z1a1";
String[] split = s.split("a|z");
System.out.println(Arrays.toString(split));
运行结果:[192, 168, 1, 1]
字符串截取
方法名 | 描述 |
---|---|
public String substring(int beginIndex) | 指定索引截取到末尾, |
public String substring(in beginIndex, int endIndex) | 截取两个索引之间的值 |
- 索引从0开始
- 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标
其他方法
方法名 | 描述 |
---|---|
public .String. trim() | 去掉字符串左右空格,包括换行符,制表符 |
public.String . toUpperCase() | 转大写//只包括字母 |
public . String . to lowerCase() | 转小写//只包括字母 |
public .native . String . intern() | 字符串入字符串常量池 |
public . String . concat(String str) | 字符串连接不入池 |
public . boolean isEmptv() | 判断字符串是否为 “” 空字符串,不是判断是否为null引用 |
首字母大写的方法:
public static void main(String[] args) {
System.out.println(fistUpper("yuisama"));
System.out.println(fistUpper(""));
System.out.println(fistUpper("a"));
}
public static String fistUpper(String str) {
if ("".equals(str)||str==null) {
return str ;
}
if (str.length()>1) {
return str.substring(0, 1).toUppeCase()+str.substring(1) ;
}
return str.toUpperCase() ;
}
先截取后连接.同时也要注意空字符串的判断
三 StringBuffer和 StringBuilder
String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
StringBuffer与StringBuilder大部分功能是相似的
StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安
为什么要使用
因为平时开发中我们需要对字符串进行操作如果使用 '+‘对字符串进行拼接操作的时候我们经常会发现效率比较低,因为String类是通过char[]数组进行实现的,但是因为String的char[]变量用final修饰不能进行修改,所以在进行拼接的时候效率偏低.
从反编译代码上来看,在使用’+'拼接字符串的时候
String a = "a";
String b = "b";
String c = a+b;
可以看出他在拼接过程中使用了两次StringBuilder的对象对字符串机进行了拼接操作,并且在最后使用了toString方法进行还原.
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<\init>": ()V
13: aload_1
14: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_2
18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
24: astore_3
25: return
可想而知如果有大量字符串使用 ‘+’ 拼接操作的话,会产生很多的对象并且只是用一次就废弃,对内存开销和运行时内存回收导致的时间开销影响是很大的.
所以我们在对字符串进行修改一系列操作的时候尽量使用StringBuilder和StringBuffer类进行.
当然如果不考虑线程安全,大多数情况下StringBuilder的效率比StringBuffer稍高,且两者的方法基本相同.如果在编译阶段可以确定字符串常量的话直接使用String str = “aa”+"bbb"这样的语句效率最高,
常用方法
方法名 | 描述 |
---|---|
String 变为 StringBuffer: | 利用StringBuffer的构造方法或append()方法 |
StringBuffer 变为 String: | 调用toString()方法。 |
StringBuffer append(String str) | 字符串拼接 |
StringBuffer reverse(String str) | 字符串翻转 |
StringBuffer delete(int start ,int end) | 删除指定范围的数据 |
StringBuffer insert(int offset, 各种数据类型 b) | 插入数据 |