【码道】字符串操作详解

【码道】系列博客致力于为广大Java学习者提供清晰、系统的学习路径。从基础语法到高级特性,从理论讲解到实战应用,我们将用简洁易懂的语言,带您循序渐进地掌握Java编程精髓。无论您是初学者还是希望巩固基础的开发者,都能在这里找到成长为Java高手的捷径。让我们一起探索编程之道,体验Java的无限魅力!

一、字符串:程序中的文本处理核心

在编程世界中,文本数据无处不在。从用户名、密码到文章内容,从配置文件到网页内容,我们需要不断地处理各种文本信息。在Java中,字符串(String)是处理文本的基础工具,也是使用频率最高的引用类型之一。

字符串本质上是字符的有序序列。例如,"Hello"是由’H’、‘e’、‘l’、‘l’、'o’五个字符组成的字符串。今天,我们将深入学习Java中字符串的各种操作方法。

二、String类基础

在Java中,字符串由String类表示,它是Java标准库中的核心类,位于java.lang包中(无需显式导入)。

1. 字符串的特点

  • 不可变性:一旦创建,字符串的内容不能修改
  • 字符序列:本质上是一系列Unicode字符的集合
  • 线程安全:因为不可变,所以天然线程安全
  • 特殊地位:Java对字符串提供了特殊支持,如字符串字面量

三、创建字符串

Java中创建字符串有多种方式:

1. 字符串字面量

最常见的方式是使用字符串字面量(双引号括起的文本):

String name = "张三";
String message = "你好,世界!";

2. 使用new关键字

可以通过new关键字显式创建字符串对象:

String city = new String("北京");
char[] chars = {'上', '海'};
String city2 = new String(chars);

3. 字符串常量池

为了提高效率,Java维护了一个字符串常量池。使用字面量创建的字符串会被放入池中重用:

String s1 = "hello";
String s2 = "hello";  // 不会创建新对象,而是复用s1引用的对象
String s3 = new String("hello");  // 强制创建新对象,不使用常量池

四、字符串的不可变性

String对象一旦创建,它的值就不能改变。这看起来与我们的直觉相反:

String name = "张";
name = name + "三";  // 看起来修改了字符串,但实际上...

实际发生的是:

  1. 创建了字符串"张"
  2. 创建了新字符串"三"
  3. 创建了新字符串"张三"
  4. 变量name的引用改为指向新创建的"张三"
  5. 原来的"张"字符串对象依然存在,只是没有引用指向它了

这种不可变性虽然看起来低效,但带来了很多好处:

  • 安全性:不会被意外修改
  • 线程安全:多线程可以共享访问
  • 哈希操作优化:可以缓存哈希码

五、常用字符串操作方法

1. 获取字符串信息

String text = "Hello, Java!";

// 获取长度
int length = text.length();  // 12

// 检查是否为空
boolean isEmpty = text.isEmpty();  // false

// 获取特定位置的字符(索引从0开始)
char firstChar = text.charAt(0);  // 'H'

2. 查找和子串操作

String sentence = "Java是世界上最流行的编程语言之一";

// 查找子串位置
int index = sentence.indexOf("流行");  // 8
int lastIndex = sentence.lastIndexOf("语言");  // 12

// 检查前缀和后缀
boolean startsWithJava = sentence.startsWith("Java");  // true
boolean endsWithOne = sentence.endsWith("之一");  // true

// 提取子串
String sub1 = sentence.substring(8);  // "流行的编程语言之一"
String sub2 = sentence.substring(8, 10);  // "流行"

3. 字符串修改操作

由于不可变性,这些操作实际上都是创建新的字符串:

String original = "Hello, World!";

// 转换大小写
String upper = original.toUpperCase();  // "HELLO, WORLD!"
String lower = original.toLowerCase();  // "hello, world!"

// 替换字符或子串
String replaced = original.replace('l', 'L');  // "HeLLo, WorLd!"
String replacedStr = original.replace("World", "Java");  // "Hello, Java!"

// 去除首尾空白
String withSpaces = "  trim example  ";
String trimmed = withSpaces.trim();  // "trim example"

// 连接字符串
String firstName = "张";
String lastName = "三";
String fullName = firstName.concat(lastName);  // "张三"

4. 字符串分割和连接

// 分割字符串
String csvLine = "苹果,香蕉,葡萄,橙子";
String[] fruits = csvLine.split(",");  // ["苹果", "香蕉", "葡萄", "橙子"]

// 使用静态方法连接
String[] words = {"This", "is", "a", "test"};
String joined = String.join(" ", words);  // "This is a test"

六、字符串比较

1. equals方法:比较内容

String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");

System.out.println(s1.equals(s2));  // true(内容相同)
System.out.println(s1.equals(s3));  // true(内容相同)
System.out.println(s1 == s2);       // true(同一对象,都来自常量池)
System.out.println(s1 == s3);       // false(不同对象)

2. 忽略大小写比较

String name1 = "Java";
String name2 = "java";
System.out.println(name1.equalsIgnoreCase(name2));  // true

3. 比较字符串大小(字典顺序)

String word1 = "apple";
String word2 = "banana";
int result = word1.compareTo(word2);  // 负数,表示word1<word2

七、字符串格式化

Java提供了类似C语言printf的格式化功能:

String name = "张三";
int age = 25;
double height = 175.5;

// 格式化字符串
String info = String.format("姓名:%s,年龄:%d岁,身高:%.1f厘米", name, age, height);
// 输出: 姓名:张三,年龄:25岁,身高:175.5厘米

// 常用格式说明符
// %s - 字符串
// %d - 整数
// %f - 浮点数(%.2f 表示保留2位小数)
// %c - 字符
// %b - 布尔值
// %n - 换行符

// 直接使用printf方法输出格式化字符串
System.out.printf("欢迎%s光临,您是今天第%d位顾客%n", name, 5);

八、StringBuilder和StringBuffer:高效字符串构建

由于String的不可变性,大量拼接字符串会产生大量临时对象,效率低下:

String result = "";
for (int i = 0; i < 1000; i++) {
    result += i;  // 低效,每次都创建新字符串
}

Java提供了两个可变字符序列类用于高效构建字符串:

1. StringBuilder(非线程安全,但更高效)

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append(i);  // 高效,不创建临时对象
}
String result = sb.toString();

2. StringBuffer(线程安全,略微慢一些)

StringBuffer buffer = new StringBuffer();
buffer.append("Hello");
buffer.append(" ");
buffer.append("World");
String result = buffer.toString();  // "Hello World"

3. 常用方法

StringBuilder builder = new StringBuilder("Hello");

// 添加内容
builder.append(" World");  // "Hello World"

// 插入内容
builder.insert(5, ",");  // "Hello, World"

// 删除内容
builder.delete(5, 7);  // "Hello World"

// 替换内容
builder.replace(6, 11, "Java");  // "Hello Java"

// 反转
builder.reverse();  // "avaJ olleH"

4. 性能对比

// 测量String拼接和StringBuilder的性能差异
long startTime = System.currentTimeMillis();

// 使用String拼接
String s = "";
for (int i = 0; i < 100000; i++) {
    s += "a";
}

long endTime = System.currentTimeMillis();
System.out.println("String拼接耗时:" + (endTime - startTime) + "毫秒");

// 使用StringBuilder
startTime = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100000; i++) {
    sb.append("a");
}
String result = sb.toString();
endTime = System.currentTimeMillis();
System.out.println("StringBuilder耗时:" + (endTime - startTime) + "毫秒");

九、正则表达式与字符串

Java String类提供了与正则表达式配合使用的方法:

1. 匹配

String email = "user@example.com";
boolean isEmail = email.matches("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}");
System.out.println("是否是合法邮箱:" + isEmail);  // true

2. 替换

String text = "我的电话是123-456-7890和987-654-3210";
// 将所有电话号码替换为"***-***-****"
String anonymized = text.replaceAll("\\d{3}-\\d{3}-\\d{4}", "***-***-****");
// 输出:我的电话是***-***-****和***-***-****

3. 分割

// 按照多种分隔符分割字符串
String data = "apple,banana;cherry|grape";
String[] fruits = data.split("[,;|]");  // ["apple", "banana", "cherry", "grape"]

十、实用示例:文本处理应用

我们来看一个简单的短信统计应用,综合使用字符串操作:

public class SMSAnalyzer {
    public static void main(String[] args) {
        String message = "亲爱的用户,您的订单#12345已发货,预计3天内送达。如有问题,请联系客服电话400-123-4567。祝您生活愉快!【某某商城】";
        
        // 1. 基本信息统计
        int length = message.length();
        int charCount = message.replaceAll("\\s", "").length();  // 去除空白后的字符数
        
        // 2. 提取订单号
        String orderPattern = "#(\\d+)";
        java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(orderPattern);
        java.util.regex.Matcher matcher = pattern.matcher(message);
        String orderNumber = matcher.find() ? matcher.group(1) : "未找到订单号";
        
        // 3. 提取联系电话
        String phonePattern = "(\\d{3}-\\d{3}-\\d{4})";
        pattern = java.util.regex.Pattern.compile(phonePattern);
        matcher = pattern.matcher(message);
        String contactPhone = matcher.find() ? matcher.group(1) : "未找到联系电话";
        
        // 4. 匿名化处理
        String anonymizedMessage = message.replaceAll(phonePattern, "***-***-****");
        
        // 5. 分割成句子
        String[] sentences = message.split("[。!?]");
        
        // 6. 检查是否包含特定内容
        boolean isOrderMessage = message.contains("订单");
        boolean isPromotional = message.endsWith("】") && message.contains("【");
        
        // 7. 使用StringBuilder构建报告
        StringBuilder report = new StringBuilder();
        report.append("短信分析报告\n");
        report.append("========================\n");
        report.append(String.format("总字符数: %d\n", length));
        report.append(String.format("实际内容字符数: %d\n", charCount));
        report.append(String.format("订单号: %s\n", orderNumber));
        report.append(String.format("联系电话: %s\n", contactPhone));
        report.append(String.format("是否是订单消息: %b\n", isOrderMessage));
        report.append(String.format("是否是营销短信: %b\n", isPromotional));
        report.append("\n句子分析:\n");
        
        for (int i = 0; i < sentences.length; i++) {
            String sentence = sentences[i].trim();
            if (!sentence.isEmpty()) {
                report.append(String.format("第%d句: %s\n", i+1, sentence));
            }
        }
        
        report.append("\n匿名化后的短信:\n");
        report.append(anonymizedMessage);
        
        System.out.println(report.toString());
    }
}

十一、字符串操作的性能建议

  1. 合理使用字符串拼接

    • 少量拼接:可以使用+运算符
    • 大量拼接:使用StringBuilder
  2. 减少临时字符串对象

    • 避免在循环中使用+拼接字符串
    • 考虑使用字符数组替代字符串进行频繁操作
  3. 正确使用字符串比较

    • 比较内容用equals(),不要用==
    • 大小写不敏感比较用equalsIgnoreCase()
  4. 利用字符串池

    • 对于常量字符串,优先使用字面量而不是new
  5. 合理使用正则表达式

    • 复杂正则表达式可以预编译,避免重复编译
    • 简单匹配考虑使用indexOf()等方法代替正则

十二、总结

Java中的字符串操作涵盖了从基本的字符获取、子串提取到高级的正则表达式匹配等多种功能。虽然String对象本身是不可变的,但通过各种方法和辅助类,我们可以高效地进行各种文本处理任务。

掌握字符串操作是Java编程的基础技能,几乎所有Java应用都会涉及到文本处理。从用户输入验证到数据分析,从文件处理到网络通信,字符串操作无处不在。

在实际开发中,请记住:

  • 合理选择String、StringBuilder或StringBuffer,根据场景优化性能
  • 理解String的不可变性及其影响
  • 熟练使用正则表达式进行复杂的文本匹配和处理
java字符串操作大全,适合初学者,浅显易懂 部JAVA字符串操作 2008-07-11 15:39:42| 分类: JAVA | 标签: |字号大中小 订阅 . JAVA字符串的方法 String a = "53c015"; //Integer.parseInt(s, radix) radix设置为10,表示10进制,16表示16进制啦 int i = Integer.parseInt(a, 16); 1、length() 字符串的长度   例:char chars[]={'a','b'.'c'};     String s=new String(chars);     int len=s.length(); 2、charAt() 截取一个字符   例:char ch;     ch="abc".charAt(1); 返回'b' 3、getChars() 截取多个字符   void getChars(int sourceStart,int sourceEnd,char target[],int targetStart)   sourceStart指定了子串开始字符的下标,sourceEnd指定了子串结束后的下一个字符的下标。因此,子串包含从sourceStart到sourceEnd-1的字符。接收字符的数组由target指定,target中开始复制子串的下标值是targetStart。   例:String s="this is a demo of the getChars method.";     char buf[]=new char[20];     s.getChars(10,14,buf,0); 4、getBytes()   替代getChars()的一种方法是将字符存储在字节数组中,该方法即getBytes()。 5、toCharArray() 6、equals()和equalsIgnoreCase() 比较两个字符串 7、regionMatches() 用于比较一个字符串中特定区域与另一特定区域,它有一个重载的形式允许在比较中忽略大小写。   boolean regionMatches(int startIndex,String str2,int str2StartIndex,int numChars)   boolean regionMatches(boolean ignoreCase,int startIndex,String str2,int str2StartIndex,int numChars) 8、startsWith()和endsWith()   startsWith()方法决定是否以特定字符串开始,endWith()方法决定是否以特定字符串结束 9、equals()和==   equals()方法比较字符串对象中的字符,==运算符比较两个对象是否引用同一实例。   例:String s1="Hello";     String s2=new String(s1);     s1.eauals(s2); //true     s1==s2;//false 10、compareTo()和compareToIgnoreCase() 比较字符串 11、indexOf()和lastIndexOf()   indexOf() 查找字符或者子串第一次出现的地方。   lastIndexOf() 查找字符或者子串是后一次出现的地方。 12、substring()   它有两种形式,第一种是:String substring(int startIndex)          第二种是:String substring(int startIndex,int endIndex) 13、concat() 连接两个字符串 14 、replace() 替换   它有两种形式,第一种形式用一个字符在调用字符串中所有出现某个字符的地方进行替换,形式如下:   String replace(char original,char replacement)   例如:String s="Hello".replace('l','w');   第二种形式是用一个字符序列替换另一个字符序列,形式如下:   String replace(CharSequence original,CharSequence replacement) 15、trim() 去掉起始和结尾的空格 16、valueOf() 转换为字符串 17、toLowerCase() 转换为小写 18、toUpperCase() 转换为大写 19、StringBuffer构造函数   StringBuffer定义了三个构造函数:   StringBuffer()   StringBuffer(int size)   StringBuffer(String str)   StringBuffer(CharSequence chars)      (1)、length()和capacity()     一个StringBuffer当前长度可通过length()方法得到,而整个可分配空间通过capacity()方法得到。      (2)、ensureCapacity() 设置缓冲区的大小     void ensureCapacity(int capacity)   (3)、setLength() 设置缓冲区的长度     void setLength(int len)   (4)、charAt()和setCharAt()     char charAt(int where)     void setCharAt(int where,char ch)   (5)、getChars()     void getChars(int sourceStart,int sourceEnd,char target[],int targetStart)   (6)、append() 可把任何类型数据的字符串表示连接到调用的StringBuffer对象的末尾。     例:int a=42;       StringBuffer sb=new StringBuffer(40);       String s=sb.append("a=").append(a).append("!").toString();   (7)、insert() 插入字符串     StringBuffer insert(int index,String str)     StringBuffer insert(int index,char ch)     StringBuffer insert(int index,Object obj)     index指定将字符串插入到StringBuffer对象中的位置的下标。   (8)、reverse() 颠倒StringBuffer对象中的字符     StringBuffer reverse() 分代如下
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luck_ff0810

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值