String —— 一种特殊的数据类型

114 阅读7分钟

在C语言里面,是没有字符串这种数据类型的! 而 C++ 和Java中有,叫做String ,String是一种特殊的数据类型。与String相似的还有StringBuilderStringBuffer,它们之间又有什么联系和区别呢?相信你接下来会找到答案的!

字符,字节与字符串

  1. 什么是字符串?

使用 双引号 引起来的就是字符串

  1. 什么是字符?

使用 单引号 引起来的就是字符

  • Java中没有所谓的字符串以\0结尾的说法
  • 字符,字节与字符串之间可以相互转换

如何理解字符串拼接?

字符串拼接:每次拼接都会new一个新的对象,所以原来的字符串其实是没有改变的

因此也说明了String中的内容是不可修改的,即**字符串不可变**。

字符和字符串

  1. 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);
}
  1. 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);
}
  1. 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);
}
  1. 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]+" ");
    }
}

字节与字符串

  1. public String(byte bytes[]) 构造方法

将字节数组变为字符串

public static void main(String[] args) {
    byte[] bytes = {97,98,99};
    String str = new String(bytes);
    System.out.println(str);
}
  1. 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为采用同步处理,属于线程不安全操作