引
在C语言里面,是没有字符串这种数据类型的! 而 C++ 和Java中有,叫做String ,String是一种特殊的数据类型。与String相似的还有StringBuilder和StringBuffer,它们之间又有什么联系和区别呢?相信你接下来会找到答案的!
字符,字节与字符串
- 什么是字符串?
使用 双引号 引起来的就是字符串
- 什么是字符?
使用 单引号 引起来的就是字符
- Java中没有所谓的字符串以\0结尾的说法
- 字符,字节与字符串之间可以相互转换
如何理解字符串拼接?
字符串拼接:每次拼接都会new一个新的对象,所以原来的字符串其实是没有改变的
因此也说明了String中的内容是不可修改的,即**字符串不可变**。
字符和字符串
- public String(char value[]) 构造方法
将字符数组中的所有内容变为字符串
public static void main(String[] args) { char[] chars = new char[]{'a','b','c','d','e'}; String str = new String(chars); System.out.println(str); }
- public String(char value[], int offset, int count) 构造方法
将字符数组 char value[] 中的指定内容变为字符串 int offset 偏移位置下标, int count 取多少个字符
public static void main(String[] args) { char[] chars = new char[]{'a','b','c','d','e'}; String str = new String(chars,1,3); System.out.println(str); }
- public char charAt(int index) 普通方法
取得指定索引位置的字符,索引从0开始 获取到index下标的那个字符
public static void main(String[] args) { String str = "hello"; char ch = str.charAt(2); System.out.println(ch); }
- public char[] toCharArray() 普通方法
将字符串变为字符数组返回
public static void main(String[] args) { String str = "hello"; //把str指向的字符串对象转变为字符数组 char[] ch = str.toCharArray(); //System.out.println(Arrays.toString(ch)); for (int i = 0; i < ch.length; i++) { System.out.print(ch[i]+" "); } }
字节与字符串
- public String(byte bytes[]) 构造方法
将字节数组变为字符串
public static void main(String[] args) { byte[] bytes = {97,98,99}; String str = new String(bytes); System.out.println(str); }
- public String(byte bytes[], int offset, int count) 构造方法
将部分字节数组中的内容变为字符串
public static void main(String[] args) { byte[] bytes = {97, 98, 99}; String str = new String(bytes,1,2); System.out.println(str); }3.public byte[] getBytes() 普通方法 将字符串以字节数组的形式返回
public static void main(String[] args) { String str = "abc"; byte[] bytes = str.getBytes(); System.out.println(Arrays.toString(bytes)); }4.public byte[] getBytes(String charsetName) throws UnsupportedEncodingException 普通方法 编码转换处理
public static void main(String[] args) throws UnsupportedEncodingException { String str = "汉字"; byte[] bytes = str.getBytes("GBK"); System.out.println(Arrays.toString(bytes)); }
常量池
在学习常量池之前,我们得了解到什么是池。 什么是池?池有哪些? 1、数据库连接池 2、线程池 ········· 等还有其他很多的池 池的意义:提高效率(简单理解就是池里有就不放了,没有再放,用的时候去池子里取) 下面来主要介绍一下以下三个常量池class文件常量池,运行时常量池,字符串常量池。
class文件常量池
程序编译好了,会生成字节码文件【字节码文件是放在磁盘上的】。在编译时,像int a = 10;这种就放在class文件常量池
运行时常量池
当程序把编译好的字节码文件加载到jvm当中后,会生成一个运行时常量池【在方法区】,实际上运行时常量池时由class文件常量池而来的。即把class加载到jvm时class文件常量池---->运行时常量池
字符串常量池
主要存放字符串常量,字符串常量池本质上是一个哈希表【称作StringTable】
只有双引号引起来的字符串常量才会放入字符串常量池里!!!
注意:
- 运行时常量池放在方法区
- 字符串常量池放在堆里面,也就是说堆里面会维护一张哈希表,在哈希表里面来存储字符串常量
哈希表
什么是哈希表? 哈希表:简单来说哈希表是一种数据结构--->描述和组织数据的一种方式。
哈希表是如何做的?
哈希表是这样做的:存储数据的时候,会根据一个**映射关系**进行存储,如何映射,需要设计一个函数(哈希函数)
那映射关系又什么?
映射关系简单理解就是我怎么存的就怎么取,它的速度非常快可以达到O(1)
字符串常见操作
- 字符串比较
- 字符串查找
- 字符换替换
- 字符串拆分
- 字符串截取
- 及其其他操作方法
字符串比较
1.public boolean equals(Object anObject) 区分大小写的比较
public static void main(String[] args) { String str = "hello"; String str1 = "HELLO"; System.out.println(str.equals(str1)); }2.public boolean equalsIgnoreCase(String anotherString) 不区分大小写的比较
public static void main(String[] args) { String str = "hello"; String str1 = "HELLO"; System.out.println(str.equalsIgnoreCase(str1)); }3.public int compareTo(String anotherString) 比较两个字符串的大小关系
public static void main(String[] args) { String str = "hello"; String str1 = "HELLO"; int ret = str.compareTo(str1); System.out.println(ret); }
字符串查找
1.public boolean contains(CharSequence s) 普通方法 判断一个字符串是否存在
public static void main(String[] args) { String str = "hello"; String str1 = "hk"; boolean flag = str.contains(str1); System.out.println(flag); }2.public int indexOf(String str) 普通方法 从头开始查找字符串的位置,找到了返回下标,找不到返回 -1
public static void main(String[] args) { String str = "ababcabcd"; int ret = str.indexOf("abc"); System.out.println(ret); }3.public int indexOf(String str, int fromIndex) 从指定位置开始查找子字符串的位置
public static void main(String[] args) { String str = "abababc"; int ret = str.indexOf("a",2); System.out.println(ret); }4.public int lastIndexOf(String str) 由后向前开始查找子字符串的位置
public static void main(String[] args) { String str = "hello"; int ret = str.lastIndexOf("e"); System.out.println(ret); }5.public int lastIndexOf(String str, int fromIndex) 从指定位置由后向前查找子字符串的位置
public static void main(String[] args) { String str = "ababcabcab"; int ret = str.lastIndexOf("b",3); System.out.println(ret); }6.public boolean startsWith(String prefix) 判断是否以指定字符串开头
public static void main(String[] args) { String str = "hello"; boolean ret = str.startsWith("heo"); System.out.println(ret); }7.public boolean startWith(String prefix, int fromIndex) 从指定位置开始判断是否以指定字符串开头
public static void main(String[] args) { String str = "hello"; boolean ret = str.startsWith("lo",3); System.out.println(ret); }8.public boolean endsWith(String suffix) 判断是否以指定字符串结尾
public static void main(String[] args) { String str = "ababcabcab"; boolean ret = str.endsWith("c"); System.out.println(ret); }
字符串替换
1.public String replaceAll(String regex, String replacement) 替换所有的指定内容
public static void main(String[] args) { String str = "hello"; String ret = str.replaceAll(str,"world"); System.out.println(ret); }2.public String replaceFirst(String regex, String replacement) 替换首个内容
public static void main(String[] args) { String str = "helloeeee"; String ret = str.replaceFirst("e","k"); System.out.println(ret); }
字符串拆分(重要)
1.public String[] split(String regex) 将字符串全部拆分
//分两次拆分 public static void main(String[] args) { String str = "name=zhangsan&age=18"; String[] ret = str.split("&"); for (String str1 : ret) { //System.out.println(str1); String[] str2 = str1.split("="); for (String str3 : str2) { System.out.println(str3); } } }//用 | 符号号一次拆分成功 public static void main(String[] args) { String str = "name=zhangsan&age=18"; String[] ret = str.split("&|="); for (String str1 : ret) { System.out.println(str1); } }2.public String[] split(String regex, int limit) 将字符串部分拆分,该数组长度就是 limit
public static void main(String[] args) { String str = "198.162.1.1"; String[] ret = str.split("\\.",2); for (String str1 : ret) { System.out.print(str1+" "); } }
字符串截取
1.public String substring(int beginIndex) 从指定位置的下标截取到结尾
public static void main(String[] args) { String str = "abcdef"; String str1 = str.substring(2); System.out.println(str1); }2.public String substring(int beginIndex, int endIndex) 截取部分内容,从指定的开始下标截取到指定的结束下标
public static void main(String[] args) { String str = "abcdef"; String str1 = str.substring(2,4); System.out.println(str1); }
其他操作方法
1.public native String trim() 去掉字符串的左右空格,保留中间空格
public static void main(String[] args) { String str = " abc def "; String str1 = str.trim(); System.out.println(str1); }2.public String toUpperCase() 字符串转大写
public static void main(String[] args) { String str = "abcDEfg"; String str1 = str.toUpperCase(); System.out.println(str1); }3.public String toLowerCase() 字符串转小写
public static void main(String[] args) { String str = "abcDEfg"; String str1 = str.toLowerCase(); System.out.println(str1); }4.public String intern() 字符串入池操作
public static void main(String[] args) { char[] chars = new char[]{'a','b','c'}; String str = new String(chars); String str1 = str.intern(); }5.public String concat(String str) 字符串连接等同于 “+”,拼接好的对象不会入池
public static void main(String[] args) { String str = "hello"; String str1 = str.concat(" world"); System.out.println(str1); }6.public int length() 取的字符串长度
public static void main(String[] args) { String str = "abcDEfg"; int ret = str.length(); System.out.println(ret); }7.public boolean isEmpty() 判断是否为空字符串,但不是null,而是长度为零
public static void main(String[] args) { String str = "abcDEfg"; boolean str1 = str.isEmpty(); System.out.println(str1); }
StringBuffer和StringBuilder和String
这三种都是数据类型 从内部的方法上来说是大同小异的
StringBuilder
append不会产生新的对象,是在原有的基础上做改动,返回的还是原来的那个字符串
使用append拼接:
public static void main(String[] args) { StringBuilder stringBuilder = new StringBuilder("abc"); stringBuilder.append("efg").append("kkk"); System.out.println(stringBuilder); }局部结论:如果是在循环里面,进行字符串的拼接,尽量不要使用String优先使用StringBuffer和StringBuilder,因为String每拼接一次就会new一个新对象,会压栈,耗费内存。
StringBuffer
StringBuffer和StringBuilder的区别在于:
- StringBuffer比Stringbuilder多了一个synchronized关键字意义是:能保证线程安全(作用相当与锁)
- StringBuffer用在多线程上,StringBuilder用在单线程上
- StringBuffer的加锁和解锁都会耗费资源的
StringBuffer和StringBuilder和String的区别
- String的内容不可修改,StringBuffer与StringBuilder的内容可修改
- StringBuffer与StringBuilder大部分功能是相似的
- StringBuffer采用同步处理,属于线程安全操作。而StringBuilder为采用同步处理,属于线程不安全操作