Java-认识String类

news2024/9/28 17:30:15

本章重点:

1. 认识 String 类

2. 了解 String 类的基本用法

3. 熟练掌握 String 类的常见操作

4. 认识字符串常量池

5. 认识 StringBuffer 和 StringBuilder

1.String类的重要性

在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提 供的字符串系列函数完成大部分操作,但是这种将数据和操作数据方法分离开的方式不符合面相对象的思想,而字 符串应用又非常广泛,因此Java语言专门提供了String类。 

2.常用方法

2.1 字符串构造

以下是常用的三种:

public static void main(String[] args) {
    // 使用常量串构造
    String s1 = "hello xiaofan";
    System.out.println(s1);
    // 直接newString对象
    String s2 = new String("hello xiaofan");
    System.out.println(s1);
    // 使用字符数组进行构造
    char[] array = {'a','b','c','d'};
    String s3 = new String(array);
    System.out.println(s1);
}

注意:

1. String是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类实例变量如下:

public static void main(String[] args) {
    // s1和s2引用的是不同对象 s1和s3引用的是同一对象
    String s1 = new String("hello");
    String s2 = new String("world");
    String s3 = s1;
    System.out.println(s1.length()); // 获取字符串长度---输出5
    System.out.println(s1.isEmpty()); // 如果字符串长度为0,返回true,否则返回false
}

 

2.2 String对象的比较 

字符串的比较是常见操作之一,比如:字符串排序。Java中总共提供了4中方式:

1. ==比较是否引用同一个对象,比较的是地址相不相同

    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int c = 10;
        // 对于基本类型变量,==比较两个变量中存储的值是否相同
        System.out.println(a == b); // false
        System.out.println(a == c); // true
        // 对于引用类型变量,==比较两个引用变量引用的是否为同一个对象
        String s1 = new String("hello");
        String s2 = new String("hello");
        String s3 = new String("world");
        String s4 = s1;
        System.out.println(s1 == s2); // false
        System.out.println(s2 == s3); // false
        System.out.println(s1 == s4); // true
    }

2. boolean equals(Object anObject) 方法:按照字典序比较

字典序:字符大小的顺序 String类重写了父类Object中equals方法,Object中equals默认按照==比较,String重写equals方法后,按照 如下规则进行比较,比如: s1.equals(s2)

public boolean equals(Object anObject) {
// 1. 先检测this 和 anObject 是否为同一个对象比较,如果是返回true
    if (this == anObject) {
        return true;
    }
// 2. 检测anObject是否为String类型的对象,如果是继续比较,否则返回false
    if (anObject instanceof String) {
// 将anObject向下转型为String类型对象
        String anotherString = (String)anObject;
        int n = value.length;
// 3. this和anObject两个字符串的长度是否相同,是继续比较,否则返回false
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
// 4. 按照字典序,从前往后逐个字符进行比较
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = new String("hello");
        String s3 = new String("Hello");
// s1、s2、s3引用的是三个不同对象,因此==比较结果全部为false
        System.out.println(s1 == s2); // false
        System.out.println(s1 == s3); // false
// equals比较:String对象中的逐个字符
// 虽然s1与s2引用的不是同一个对象,但是两个对象中放置的内容相同,因此输出true
// s1与s3引用的不是同一个对象,而且两个对象中内容也不同,因此输出false
        System.out.println(s1.equals(s2)); // true
        System.out.println(s1.equals(s3)); // false
    }

3. int compareTo(String s) 方法: 按照字典序进行比较

与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型。具体比较方式:

1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值

2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值

    public static void main(String[] args) {
        String s1 = new String("abc");
        String s2 = new String("ac");
        String s3 = new String("abc");
        String s4 = new String("abcdef");
        System.out.println(s1.compareTo(s2)); // 不同输出字符差值-1
        System.out.println(s1.compareTo(s3)); // 相同输出 0
        System.out.println(s1.compareTo(s4)); // 前k个字符完全相同,输出长度差值 -3
    }

4. int compareToIgnoreCase(String str) 方法:与compareTo方式相同,但是忽略大小写比较

public static void main(String[] args) {
    String s1 = new String("abc");
    String s2 = new String("ac");
    String s3 = new String("ABc");
    String s4 = new String("abcdef");
    System.out.println(s1.compareToIgnoreCase(s2)); // 不同输出字符差值-1
    System.out.println(s1.compareToIgnoreCase(s3)); // 相同输出 0
    System.out.println(s1.compareToIgnoreCase(s4)); // 前k个字符完全相同,输出长度差值 -3
}

2.3 字符串查找

字符串查找也是字符串中非常常见的操作,String类提供的常用查找的方法

 

public static void main(String[] args) {
    String s = "aaabbbcccaaabbbccc";
    System.out.println(s.charAt(3)); // 'b'
    System.out.println(s.indexOf('c')); // 6
    System.out.println(s.indexOf('c', 10)); // 15
    System.out.println(s.indexOf("bbb")); // 3
    System.out.println(s.indexOf("bbb", 10)); // 12
    System.out.println(s.lastIndexOf('c')); // 17
    System.out.println(s.lastIndexOf('c', 10)); // 8
    System.out.println(s.lastIndexOf("bbb")); // 12
    System.out.println(s.lastIndexOf("bbb", 10)); // 3
}

2.4 转化

1. 数值和字符串转化

public static void main(String[] args) {
// 数字转字符串
    String s1 = String.valueOf(1234);
    String s2 = String.valueOf(12.34);
    String s3 = String.valueOf(true);
    //String s4 = String.valueOf(new Student("Hanmeimei", 18));
    System.out.println(s1);
    System.out.println(s2);
    System.out.println(s3);
    //System.out.println(s4);
    System.out.println("=================================");
// 字符串转数字
// 注意:Integer、Double等是Java中的包装类型,这个后面会讲到
    int data1 = Integer.parseInt("1234");
    double data2 = Double.parseDouble("12.34");
    System.out.println(data1);
    System.out.println(data2);
}

2. 大小写转换

public static void main(String[] args) {
    String s1 = "hello";
    String s2 = "HELLO";
// 小写转大写
    System.out.println(s1.toUpperCase());
// 大写转小写
    System.out.println(s2.toLowerCase());
}

3. 字符串转数组

public static void main(String[] args) {
    String s = "hello";
// 字符串转数组
    char[] ch = s.toCharArray();
    for (int i = 0; i < ch.length; i++) {
        System.out.print(ch[i]);
    }
    System.out.println();
// 数组转字符串
    String s2 = new String(ch);
    System.out.println(s2);
}

4. 格式化

public static void main(String[] args) {
    String s = String.format("%d-%d-%d", 2019, 9,14);
    System.out.println(s);
}

2.5 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据,可用的方法如下:

 

public static void main(String[] args) {
    String str = "helloworld" ;
    System.out.println(str.replaceAll("l", "_")); //替换所有
    System.out.println(str.replaceFirst("l", "_"));  //替换第一个
}

由于字符串是不可变对象, 替换不修改当前字符串, 而是产生一个新的字符串.

2.6 字符串拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。

 

public static void main(String[] args) {
    String str = "hello world hello xiaofan" ;
    String[] result = str.split(" ") ; // 按照空格拆分
    for(String s: result) {
        System.out.println(s);
    }
    String str1 = "hello world hello xiaofan" ;
    String[] result1 = str.split(" ",2) ;
    for(String s: result1) {
        System.out.println(s);
    }

//特殊情况,拆分ip地址
    String str = "192.168.1.1" ;
    String[] result = str.split("\\.") ;
    for(String s: result) {
        System.out.println(s);
    }
}


注意事项:

1. 字符"|","*","+"都得加上转义字符,前面加上"\\" .

2. 而如果是"\\" ,那么就得写成"\\\\" .

3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.

public static void main(String[] args) {
    //多次拆分
    String str = "name=zhangsan&age=18" ;
    String[] result = str.split("&") ;
    for (int i = 0; i < result.length; i++) {
        String[] temp = result[i].split("=") ;
        System.out.println(temp[0]+" = "+temp[1]);
    }
}

2.7 字符串截取

public static void main(String[] args) {
    String str = "helloworld" ;
    System.out.println(str.substring(5));
    System.out.println(str.substring(0, 5));
}

1. 索引从0开始

2. 注意前闭后开区间的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

2.8 其他操作方法

    public static void main(String[] args) {
        //trim 会去掉字符串开头和结尾的空白字符(空格, 换行, 制表符等).
        String str = " hello world " ;
        System.out.println("["+str+"]");
        System.out.println("["+str.trim()+"]");

    }

 2.9 字符串的不可变性

String是一种不可变对象. 字符串中的内容是不可改变。字符串不可被修改,是因为:

1. String类在设计时就是不可改变的,String类实现描述中已经说明了

2. 所有涉及到可能修改字符串内容的操作都是创建一个新对象,改变的是新对象

final修饰类表明该类不想被继承,final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内 容是可以修改的。 

为什么 String 要设计成不可变的?(不可变对象的好处是什么?)

 1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑写时拷贝的问题了.

2. 不可变对象是线程安全的.

3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.

2.10 字符串修改

注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。

public static void main(String[] args) {
    String s = "hello";
    s += " world";
    System.out.println(s); // 输出:hello world


    long start = System.currentTimeMillis();
    String s = "";
    for(int i = 0; i < 10000; ++i){
        s += i;
    }
    long end = System.currentTimeMillis();
    System.out.println(end - start);
    start = System.currentTimeMillis();
    StringBuffer sbf = new StringBuffer("");
    for(int i = 0; i < 10000; ++i){
        sbf.append(i);
    }
    end = System.currentTimeMillis();
    System.out.println(end - start);
    start = System.currentTimeMillis();
    StringBuilder sbd = new StringBuilder();
    for(int i = 0; i < 10000; ++i){
        sbd.append(i);
    }
    end = System.currentTimeMillis();
    System.out.println(end - start);
}

可以看待在对String类进行修改时,效率是非常慢的,因此:尽量避免对String的直接需要,如果要修改建议尽量 使用StringBuffer或者StringBuilder。 借助StringBuffer 和 StringBuilder来修改

3. StringBuilder和StringBuffer

3.1 StringBuilder的介绍

由于String的不可更改特性,为了方便字符串的修改,Java中又提供StringBuilder和StringBuffer类。这两个类大 部分功能是相同的,这里介绍 StringBuilder常用的一些方法

public static void main(String[] args) {
    StringBuilder sb1 = new StringBuilder("hello");
    StringBuilder sb2 = sb1;
// 追加:即尾插-->字符、字符串、整形数字
    sb1.append(' '); // hello
    sb1.append("world"); // hello world
    sb1.append(123); // hello world123
    System.out.println(sb1); // hello world123
    System.out.println(sb1 == sb2); // true
    System.out.println(sb1.charAt(0)); // 获取0号位上的字符 h
    System.out.println(sb1.length()); // 获取字符串的有效长度14
    System.out.println(sb1.capacity()); // 获取底层数组的总大小
    sb1.setCharAt(0, 'H'); // 设置任意位置的字符 Hello world123
    sb1.insert(0, "Hello world!!!"); // Hello world!!!Hello world123
    System.out.println(sb1);
    System.out.println(sb1.indexOf("Hello")); // 获取Hello第一次出现的位置
    System.out.println(sb1.lastIndexOf("hello")); // 获取hello最后一次出现的位置
    sb1.deleteCharAt(0); // 删除首字符
    sb1.delete(0,5); // 删除[0, 5)范围内的字符
    String str = sb1.substring(0, 5); // 截取[0, 5)区间中的字符以String的方式返回
    System.out.println(str);
    sb1.reverse(); // 字符串逆转
    str = sb1.toString(); // 将StringBuffer以String的方式返回
    System.out.println(str);
}

String和StringBuilder最大的区别在于String的内容无法修改,而StringBuilder的内容可以修改。频繁修改字符串的情况考虑使用StringBuilder。

注意:String和StringBuilder类不能直接转换。如果要想互相转换,可以采用如下原则: String变为StringBuilder: 利用StringBuilder的构造方法或append()方法 StringBuilder变为String: 调用toString()方法。

 String、StringBuffer、StringBuilder的区别:

String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.

StringBuffer与StringBuilder大部分功能是相似的

StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作

String的OJ练习题:

import jdk.nashorn.internal.ir.WhileNode;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @author xiaofan
 * @version 1.0
 * @date 2023/11/18 22:03
 */
public class Test1 {
    //字符串中的第一个唯一字符
    //在给定一个字符s,找到它的第一个不重复的字符,并返回它的索引,如果不存在,则返回-1
    public static int  firstUniqChar(String s){
        int[] count = new int[26];
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            count[ch-'a']++;
        }
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (count[ch-'a'] == 1){
                return i;
            }
        }
        return 1;

    }
    public static void main1(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String input = scanner.nextLine();
        System.out.println(firstUniqChar(input));

    }

    //计算字符串最后一个单词的长度,单词以空格隔开
    public static void main2(String[] args) {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            String s = scanner.nextLine();
            String[] str = s.split(" ");
            //int index = s.lastIndexOf(' ');
            //String str = s.substring(index+1);
            //int s1 = str[str.length-1].length();
            System.out.println(str[str.length-1].length());
        }
    }


    //如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。
    //字母和数字都属于字母数字字符
    public  boolean isNumOrCharacter(char ch){
        if (ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z'){
            return true;
        }
        return false;
    }

    public boolean isPalindrome(String s){
        s = s.toLowerCase();
        //1. 定义i 和 j
        int i = 0;
        int j = s.length()-1;
        //2.  如果i != j
        while (i <j){
            char ch = s.charAt(i);
            //3. i要一直走到一个合法的字符哪里,有可能i要走很多步
            while (i < j && !isNumOrCharacter(s.charAt(i))){
                i++;
            }
            //4. j要一直走到一个合法的字符哪里,有可能i要走很多步
            while (i < j && !isNumOrCharacter(s.charAt(j))){
                j--;
            }
            //5. 对应下标字符一样
            if (s.charAt(i) == s.charAt(j)){
                i++;
                j--;
            } else {
                //6. 对应下标字符不一样
                return  false;
            }

        }
        return true;
    }
    
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1235730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Selenium自动化测试详解

最近也有很多人私下问我&#xff0c;selenium学习难吗&#xff0c;基础入门的学习内容很多是3以前的版本资料&#xff0c;对于有基础的人来说&#xff0c;3到4的差别虽然有&#xff0c;但是不足以影响自己&#xff0c;但是对于没有学过的人来说&#xff0c;通过资料再到自己写的…

C++初阶--类型模板

文章目录 泛型编程函数模板使用通用加法函数多模板参数必须用实例化 函数模板的原理类模板使用 注意事项 泛型编程 先看一个例子&#xff1a; 这是一些对于Swap重载的函数&#xff0c;区别是类型不同&#xff1b; 虽然能够重载使用&#xff0c;但代码复用率比较低&#xff0c…

技术分享| anyRTC之RTN网络

RTN(Real-time Network)中文名&#xff1a;实时音视频传输网络。 RTN是最近几年由各大RTC的云厂商提出的一个全新架构的音视频实时传输网络概念。类似于直播的CDN网络&#xff0c;RTN是对音视频的实时性又强烈要求的场景而设计的&#xff0c;原理上全球端到端的时延通过RTN网络…

vue2【相关介绍】

目录 1&#xff1a;什么是单页面应用程序 2&#xff1a;什么是vue-cli 3&#xff1a;安装使用 4&#xff1a;vue项目的目录结构&#xff1a;​编辑 5&#xff1a;了解src目录的构成&#xff1a; 6&#xff1a;vue项目的运行流程 7&#xff1a;el&#xff1a;容器名称&…

01-了解微服务架构的演变过程和微服务技术栈

微服务 微服务架构演变 单体架构:将业务的所有功能集中在一个项目中开发最后打成一个包部署 优点: 架构简单, 部署成本低,适合小型项目缺点: 耦合度高, 升级维护困难 分布式架构:根据业务功能对系统做拆分,每个业务功能模块作为独立项目开发称为一个服务 优点: 降低服务耦合…

电脑显示msvcp140_1.dll丢失的5个常用解决方法,亲测可修复

常见于计算机操作中的"msvcp140_1.dll丢失"错误警示&#xff0c;往往令部分应用程序无法正常启动。为了解决这个问题&#xff0c;我们需要采取一些措施来修复丢失的文件。本文将介绍6个解决msvcp140_1.dll丢失的方法&#xff0c;帮助大家快速恢复计算机的正常运行。 …

SpatialFeaturePlot画图是空的

stmeta.datadplyr::left_join(stmeta.data,coor[,c(3,7:8)],by"barcodes") SpatialFeaturePlot(st,features "test",images "P02") 做了上述操作之后画出的图是空的 原因&#xff0c;left_join之后自动把stmeta.data的行名变成了1&#xff0…

算法---腐烂的橘子

题目 在给定的 m x n 网格 grid 中&#xff0c;每个单元格可以有以下三个值之一&#xff1a; 值 0 代表空单元格&#xff1b; 值 1 代表新鲜橘子&#xff1b; 值 2 代表腐烂的橘子。 每分钟&#xff0c;腐烂的橘子 周围 4 个方向上相邻 的新鲜橘子都会腐烂。 返回 直到单元格…

电机应用开发-编码器的使用

目录 编码器 增量式编码器倍频技术 常用编码器测速方法&#xff1a;M法、T法和M/T法 STM32的编码器接口 编码器接口结构体 减速电机编码器测速实验 硬件设计 TIM3配置编码器 测速环节 步进电机编码器测速实验 编码器 增量式编码器倍频技术 增量式编码器输出的常见脉…

STC单片机选择外部晶振烧录程序无法切换回内部晶振导致单片机不能使用

STC单片机选择外部晶振烧录程序无法切换回内部晶振导致单片机不能使用 1.概述 在学习51单片机过程中&#xff0c;选择了STC的12C2052AD型号单片机作为入门芯片。前几个课题实验使用默认的内部晶振烧录程序&#xff0c;运行都没有问题。 选择一个LED亮度渐变的课题做实验&…

【C++】构造函数详解

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

Vue3 源码解读系列(九)——依赖注入

依赖注入 依赖注入用于祖先组件向后代组件传递数据。 特点&#xff1a; 祖先组件不需要知道哪些后代组件在使用它提供的数据。 后代组件也不需要知道注入的数据来自哪里。 /*** provide 的实现*/ function provide(key, value) {let provides currentInstance.provides // 当…

量子计算+物流!“最后一英里”配送难题Unisys成功实时决策

&#xff08;图片来源&#xff1a;网络&#xff09; 此前&#xff0c;供应链行业一直致力于手工操作&#xff0c;严重依赖于纸质系统。后来随着客户需求的不断变化&#xff0c;这种传统方法逐渐显出不足之处。供应链行业正在迅速转向现代化&#xff0c;采用自动化和数据驱动的…

【开源】基于微信小程序的音乐平台

项目编号&#xff1a; S 055 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S055&#xff0c;文末获取源码。} 项目编号&#xff1a;S055&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示 四、核心代码4.1 查询单首…

redis的一些操作

文章目录 清空当前缓存和所有缓存配置内存大小&#xff0c;防止内存饱满设置内存淘汰策略键过期机制 清空当前缓存和所有缓存 Windows环境下使用命令行进行redis缓存清理 redis安装目录下输入cmdredis-cli -p 端口号flushdb 清除当前数据库缓存flushall 清除整个redis所有缓存…

关于一些网络的概述

语义分割网络是一种基于深度学习的计算机视觉技术,它能够将图像中的每个像素分配给特定的类别,从而实现对图像中不同对象的精确识别和定位。近年来,随着深度学习技术的不断发展,语义分割网络在各个领域都取得了显著的进展。 早期的语义分割网络主要采用全卷积神经网络(FC…

大数据分析仓库Kylin

一、Kylin 定义 Apache Kylin 是一个开源的分布式分析引擎&#xff0c;提供 Hadoop/Spark 之上的 SQL 查询接口及多维分析能力以支持超大规模数据&#xff0c;最初由 eBay 开发并贡献至开源社区。它能在亚秒内查询巨大的 Hive 表。 二、Kylin 架构 A、REST Server 是应用程序…

操作系统基础操作

操作系统的启动 体系结构概念 CPU、I/O、内存-通过总线连接 操作系统一开始存放时没有放在内存里&#xff0c;而是当在DISK中&#xff0c;由BIOS提供相应支持 DISK&#xff1a;存放OSBIOS&#xff1a;基本I/O处理系统&#xff08;计算机开机时可以让系统检测各种外设&#…

软文转化率如何提高,媒介盒子分享三大原则

决定软文推广的主要因素就在于软文内容&#xff0c;但是如何才能提高软文转化率呢&#xff1f;下面就让媒介盒子为你解答&#xff01; 一、 软文类型 软文类型按照推广目标划分主要分为品牌软文、产品软文、营销软文。 ● 品牌软文 品牌软文的目的在于扩大品牌对群众的影响力…

基于Vue+SpringBoot的桃花峪滑雪场租赁系统

项目编号&#xff1a; S 036 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S036&#xff0c;文末获取源码。} 项目编号&#xff1a;S036&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 游客服务2.2 雪场管理 三、数据库设…