掘金 后端 ( ) • 2024-04-03 14:02

在Java和Go中,字符串处理是一个无处不在且至关重要的主题。无论是在数据处理、文本解析、网络通信还是用户界面交互等方面,字符串都扮演着至关重要的角色。因此,对于开发人员来说,了解不同编程语言中的字符串处理方式以及它们的性能特点是至关重要的。

在本文中,我们将详细探讨 Java 和 Go 中字符串处理的异同。

定义初始化

在Java中,字符串可以通过多种方式进行定义和初始化

1,使用字符串字面量初始化:你可以使用双引号将字符串文字括起来,并将其分配给一个变量。
String str = "Hello, World!";


2,使用构造函数初始化:你可以使用 new 关键字和 String 类的构造函数来初始化一个字符串对象。
String str = new String("Hello, World!");


3,使用字符串连接符初始化:你可以使用加号运算符将多个字符串连接起来,并将结果分配给一个变量。
String str = "Hello" + ", " + "World" + "!";


4,使用字符串构造器初始化:你可以使用 StringBuilder 或 StringBuffer 类的构造器来创建可变的字符串,并将其转换为不可变的字符串。
StringBuilder builder = new StringBuilder();
builder.append("Hello");
builder.append(", ");
builder.append("World");
builder.append("!");
String str = builder.toString();

Go则是很简单

str := "Hello, World!"

定义和声明并不是我们今天的重点,让我们继续向下看。

字符串的各种操作方法

Java 作为一种成熟的面向对象编程语言,拥有丰富的字符串处理功能和类库。而 Go 则是一种简洁、高效的系统编程语言,它在字符串处理方面采用了不同的设计理念和实现方式。

长度获取

在 Java 中,要获取字符串的长度,你可以使用字符串的 length() 方法

public class Main {
    public static void main(String[] args) {
        // 定义一个包含中文字符的字符串
        String str = "你好,世界!";
        
        // 获取字符串的长度
        int length = str.length();
        
        // 打印字符串的长度
        System.out.println("字符串的长度为:" + length);
    }
}
//结果是6

但是对于Go语言来说,要获取字符串的长度,你可以使用内置的 len() 函数。这个函数返回的是字符串中的字节(byte)数量,而不是 Unicode 字符的数量。在 Go 中,字符串是以 UTF-8 编码存储的,一个 Unicode 字符可能由多个字节组成。

package main

import "fmt"

func main() {
    // 定义一个包含中文字符的字符串
    str := "你好,世界!"
    
    // 获取字符串的长度
    length := len(str)
    
    // 打印字符串的长度
    fmt.Println("字符串的长度为:", length)
}
。因为 Go 中的字符串是以 UTF-8 编码存储的,一个中文字符通常由 3 个字节组成(在某些情况下可能更多),所以这个字符串的长度为 18(包含了标点符号,这里的标点符号是中文的)

如果你想要获取字符串中 Unicode 字符的数量,而不是字节的数量,可以使用 utf8.RuneCountInString() 函数。这个函数会返回字符串中 Unicode 字符的数量。

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    // 定义一个包含中文字符的字符串
    str := "你好,世界!"
    
    // 获取字符串中 Unicode 字符的数量
    count := utf8.RuneCountInString(str)
    
    // 打印字符串中 Unicode 字符的数量
    fmt.Println("字符串中 Unicode 字符的数量为:", count)
}

上面的例子会返回6。四个汉字加上两个符号

当然你也可以先换成字节数组,然后计算长度,这里注意的是,如果带有中文要转成[]rune而不是[]byte;

字符串中寻找字串位置

在 Java 中,indexOf() 方法是 String 类的一个成员方法,用于在字符串中查找指定子字符串第一次出现的位置。同样,lastIndexOf()就是查找最后出现的位置。

public class Main {
    public static void main(String[] args) {
        // 定义一个字符串
        String str = "Hello, World! Hello, Java!";

        // 使用 indexOf() 方法查找指定字符的位置
        int index1 = str.indexOf('W');
        System.out.println("字符 'W' 第一次出现的位置为:" + index1);

        // 使用 indexOf() 方法从指定位置开始查找指定字符的位置
        int index2 = str.indexOf('W', 8);
        System.out.println("字符 'W' 第一次出现的位置(从索引 8 开始)为:" + index2);

        // 使用 indexOf() 方法查找指定子字符串的位置
        int index3 = str.indexOf("Java");
        System.out.println("子字符串 'Java' 第一次出现的位置为:" + index3);

        // 使用 indexOf() 方法从指定位置开始查找指定子字符串的位置
        int index4 = str.indexOf("Java", 15);
        System.out.println("子字符串 'Java' 第一次出现的位置(从索引 15 开始)为:" + index4);

        // 使用 lastIndexOf() 方法查找指定字符的最后一次出现的位置
        int lastIndex1 = str.lastIndexOf('W');
        System.out.println("字符 'W' 最后一次出现的位置为:" + lastIndex1);

        // 使用 lastIndexOf() 方法从指定位置开始查找指定字符的最后一次出现的位置
        int lastIndex2 = str.lastIndexOf('W', 14);
        System.out.println("字符 'W' 最后一次出现的位置(从索引 14 开始)为:" + lastIndex2);

        // 使用 lastIndexOf() 方法查找指定子字符串的最后一次出现的位置
        int lastIndex3 = str.lastIndexOf("Hello");
        System.out.println("子字符串 'Hello' 最后一次出现的位置为:" + lastIndex3);

        // 使用 lastIndexOf() 方法从指定位置开始查找指定子字符串的最后一次出现的位置
        int lastIndex4 = str.lastIndexOf("Hello", 13);
        System.out.println("子字符串 'Hello' 最后一次出现的位置(从索引 13 开始)为:" + lastIndex4);
    }
}

在 Go 语言中,与 Java 中的 indexOf() 方法家族类似的方法是 strings 包中的一组函数。这些函数用于在字符串中查找子字符串的位置或字符的位置。以下是一些常用的方法:

  1. strings.Index(s, substr string) int:在字符串 s 中查找子字符串 substr 第一次出现的位置,如果找到则返回子字符串的起始索引,否则返回 -1。

  2. strings.IndexRune(s string, r rune) int:在字符串 s 中查找字符 r 第一次出现的位置,如果找到则返回字符的索引,否则返回 -1。

  3. strings.LastIndex(s, substr string) int:在字符串 s 中查找子字符串 substr 最后一次出现的位置,如果找到则返回子字符串的起始索引,否则返回 -1。

  4. strings.LastIndexAny(s, chars string) int:在字符串 s 中查找字符集 chars 中任意字符最后一次出现的位置,如果找到则返回字符的索引,否则返回 -1。

  5. strings.LastIndexByte(s string, c byte) int:在字符串 s 中查找字节 c 最后一次出现的位置,如果找到则返回字节的索引,否则返回 -1。

这些方法提供了在字符串中查找子字符串或字符位置的功能,类似于 Java 中的 indexOf() 方法家族。你可以根据具体需求选择合适的函数来使用。

package main

import (
    "fmt"
    "strings"
)

func main() {
    // 定义一个字符串
    str := "Hello, World! Hello, Go!"

    // 使用 Index() 方法查找子字符串的位置
    index1 := strings.Index(str, "World")
    fmt.Println("子字符串 'World' 第一次出现的位置为:", index1)

    // 使用 IndexRune() 方法查找字符的位置
    index2 := strings.IndexRune(str, 'G')
    fmt.Println("字符 'G' 第一次出现的位置为:", index2)

    // 使用 LastIndex() 方法查找子字符串的最后一次出现的位置
    lastIndex1 := strings.LastIndex(str, "Hello")
    fmt.Println("子字符串 'Hello' 最后一次出现的位置为:", lastIndex1)

    // 使用 LastIndexAny() 方法查找字符集中任意字符的最后一次出现的位置
    lastIndex2 := strings.LastIndexAny(str, "G!")
    fmt.Println("字符集 'G!' 中任意字符最后一次出现的位置为:", lastIndex2)

    // 使用 LastIndexByte() 方法查找字节的最后一次出现的位置
    lastIndex3 := strings.LastIndexByte(str, 'l')
    fmt.Println("字节 'l' 最后一次出现的位置为:", lastIndex3)
}

是否包含字串

在 Java 中,要确定一个字符串是否包含另一个字符串,你可以使用 contains() 方法。这个方法会返回一个布尔值,表示原始字符串是否包含指定的子字符串。

public class Main {
    public static void main(String[] args) {
        // 定义一个字符串
        String str = "Hello, World!";

        // 子字符串
        String substr = "World";

        // 判断字符串是否包含子字符串
        boolean contains = str.contains(substr);

        // 打印结果
        if (contains) {
            System.out.println("字符串中包含子字符串 '" + substr + "'");
        } else {
            System.out.println("字符串中不包含子字符串 '" + substr + "'");
        }
    }
}

在上面的示例中,我们使用了 contains() 方法来判断字符串 str 是否包含子字符串 "World"。如果包含,则返回 true,否则返回 false。根据返回结果,我们打印出相应的信息。

而在 Go 语言中,要确定一个字符串是否包含另一个字符串,可以使用 strings.Contains() 函数。这个函数会返回一个布尔值,表示原始字符串是否包含指定的子字符串。

package main

import (
    "fmt"
    "strings"
)

func main() {
    // 定义一个字符串
    str := "Hello, World!"

    // 子字符串
    substr := "World"

    // 判断字符串是否包含子字符串
    contains := strings.Contains(str, substr)

    // 打印结果
    if contains {
        fmt.Println("字符串中包含子字符串", substr)
    } else {
        fmt.Println("字符串中不包含子字符串", substr)
    }
}

在上面的示例中,我们使用了 strings.Contains() 函数来判断字符串 str 是否包含子字符串 "World"。如果包含,则返回 true,否则返回 false。根据返回结果,我们打印出相应的信息。

开头和结尾

在 Java 中,要确定一个字符串是否以另一个字符串开头或者结尾,你可以使用 startsWith()endsWith() 方法。

  1. startsWith(String prefix) 方法用于检查一个字符串是否以指定的前缀开头。
  2. endsWith(String suffix) 方法用于检查一个字符串是否以指定的后缀结尾。

这两个方法都会返回一个布尔值,表示原始字符串是否满足相应的条件。

以下是示例代码:

public class Main {
    public static void main(String[] args) {
        // 定义一个字符串
        String str = "Hello, World!";

        // 检查字符串是否以指定前缀开头
        boolean startsWithHello = str.startsWith("Hello");
        System.out.println("字符串是否以 'Hello' 开头:" + startsWithHello);

        // 检查字符串是否以指定后缀结尾
        boolean endsWithWorld = str.endsWith("World");
        System.out.println("字符串是否以 'World' 结尾:" + endsWithWorld);
    }
}

在上面的示例中,我们使用了 startsWith() 方法来检查字符串 str 是否以 "Hello" 开头,并使用 endsWith() 方法来检查字符串 str 是否以 "World" 结尾。根据返回的布尔值,我们打印出相应的信息。

而在 Go 语言中,要确定一个字符串是否以另一个字符串开头或者结尾,你可以使用 strings.HasPrefix()strings.HasSuffix() 函数。

  1. strings.HasPrefix(s, prefix string) bool 函数用于检查一个字符串是否以指定的前缀开头。
  2. strings.HasSuffix(s, suffix string) bool 函数用于检查一个字符串是否以指定的后缀结尾。

这两个函数都会返回一个布尔值,表示原始字符串是否满足相应的条件。

以下是示例代码:

package main

import (
    "fmt"
    "strings"
)

func main() {
    // 定义一个字符串
    str := "Hello, World!"

    // 检查字符串是否以指定前缀开头
    startsWithHello := strings.HasPrefix(str, "Hello")
    fmt.Println("字符串是否以 'Hello' 开头:", startsWithHello)

    // 检查字符串是否以指定后缀结尾
    endsWithWorld := strings.HasSuffix(str, "World")
    fmt.Println("字符串是否以 'World' 结尾:", endsWithWorld)
}

在上面的示例中,我们使用了 strings.HasPrefix() 函数来检查字符串 str 是否以 "Hello" 开头,并使用 strings.HasSuffix() 函数来检查字符串 str 是否以 "World" 结尾。根据返回的布尔值,我们打印出相应的信息。

比较

大家都知道,在Java中,字符串比较是不能用==的。个人建议使用 Objects.equals() 方法来比较两个字符串是否相等。Objects.equals() 方法可以接受两个参数,并比较它们是否相等,包括处理 null 值的情况。

import java.util.Objects;

public class Main {
    public static void main(String[] args) {
        // 定义两个字符串
        String str1 = "Hello";
        String str2 = "Hello";
        String str3 = "World";

        // 使用 Objects.equals() 方法比较字符串
        boolean isEqual1 = Objects.equals(str1, str2);
        boolean isEqual2 = Objects.equals(str1, str3);
        System.out.println("str1 是否与 str2 相等:" + isEqual1);
        System.out.println("str1 是否与 str3 相等:" + isEqual2);
    }
}

在上面的示例中,我们使用了 Objects.equals() 方法来比较字符串 str1str2 是否相等,以及 str1str3 是否相等。这个方法会处理 null 值的情况,如果两个参数都为 null 或者都指向同一个对象,则返回 true,否则返回 false

但是在 Go 语言中可以使用 == 运算符,而且还有 strings.Compare()strings.EqualFold() 函数,它们用于字符串的比较,但有一些区别:

  1. strings.Compare() 函数

    • strings.Compare() 函数用于按照字典顺序比较两个字符串。
    • 如果第一个字符串小于第二个字符串,则返回负数(例如 -1);如果第一个字符串大于第二个字符串,则返回正数(例如 1);如果两个字符串相等,则返回 0。
    • 这个方法比较的是字符串的 Unicode 编码值,而不是字符串的内容。

    示例代码:

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        str1 := "apple"
        str2 := "banana"
    
        result := strings.Compare(str1, str2)
        fmt.Println(result) // 输出 -1
    }
    
  2. strings.EqualFold() 函数

    • strings.EqualFold() 函数用于不区分大小写地比较两个字符串是否相等。
    • 如果两个字符串的内容相同(不区分大小写),则返回 true,否则返回 false

    示例代码:

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        str1 := "Go"
        str2 := "go"
    
        result := strings.EqualFold(str1, str2)
        fmt.Println(result) // 输出 true
    }
    

总结:

  • 使用 == 运算符用于直接比较两个字符串的内容。
  • 使用 strings.Compare() 函数用于按照字典顺序比较两个字符串的 Unicode 编码值。
  • 使用 strings.EqualFold() 函数用于不区分大小写地比较两个字符串的内容。

大小写转换

在 Java 中,你可以使用以下方法来进行字符串的大小写转换:

  1. 转换为大写:

    • 使用 toUpperCase() 方法将字符串中所有字符转换为大写。
    public class Main {
        public static void main(String[] args) {
            String str = "hello world";
            String upperCaseStr = str.toUpperCase();
            System.out.println(upperCaseStr); // 输出 HELLO WORLD
        }
    }
    
  2. 转换为小写:

    • 使用 toLowerCase() 方法将字符串中所有字符转换为小写。
    public class Main {
        public static void main(String[] args) {
            String str = "HELLO WORLD";
            String lowerCaseStr = str.toLowerCase();
            System.out.println(lowerCaseStr); // 输出 hello world
        }
    }
    

以上就是在 Java 中进行字符串大小写转换的方法。

在 Go 语言中,你可以使用 strings 包中的 ToUpper()ToLower() 函数来进行字符串的大小写转换。

  1. 转换为大写:

    • 使用 strings.ToUpper() 函数将字符串中所有字符转换为大写。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        str := "hello world"
        upperCaseStr := strings.ToUpper(str)
        fmt.Println(upperCaseStr) // 输出 HELLO WORLD
    }
    
  2. 转换为小写:

    • 使用 strings.ToLower() 函数将字符串中所有字符转换为小写。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        str := "HELLO WORLD"
        lowerCaseStr := strings.ToLower(str)
        fmt.Println(lowerCaseStr) // 输出 hello world
    }
    

以上就是在 Go 语言中进行字符串大小写转换的方法。

去除字符

在 Java 中,你可以使用 trim() 方法来移除字符串两端的空白字符(空格、制表符、换行符等)。

public class Main {
    public static void main(String[] args) {
        String str = "  Hello, World!  ";
        String trimmedStr = str.trim();
        System.out.println(trimmedStr); // 输出 "Hello, World!"
    }
}

在上面的示例中,我们定义了一个包含前导和尾随空白字符的字符串 str。然后,我们使用 trim() 方法来移除这些空白字符,并将结果存储在 trimmedStr 中。最后,我们打印了 trimmedStr,得到了移除空白字符后的字符串。

而在 Go 语言中,你可以使用 strings 包中的 Trim()TrimLeft()TrimRight() 函数来移除字符串两端或指定方向的空白字符(空格、制表符、换行符等)。

  1. 移除两端空白字符:

    • 使用 strings.Trim() 函数移除字符串两端的空白字符。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        str := "  Hello, World!  "
        trimmedStr := strings.Trim(str, " \t\n")
        fmt.Println(trimmedStr) // 输出 "Hello, World!"
    }
    
  2. 移除左侧空白字符:

    • 使用 strings.TrimLeft() 函数移除字符串左侧的空白字符。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        str := "  Hello, World!  "
        trimmedStr := strings.TrimLeft(str, " \t\n")
        fmt.Println(trimmedStr) // 输出 "Hello, World!  "
    }
    
  3. 移除右侧空白字符:

    • 使用 strings.TrimRight() 函数移除字符串右侧的空白字符。
    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
        str := "  Hello, World!  "
        trimmedStr := strings.TrimRight(str, " \t\n")
        fmt.Println(trimmedStr) // 输出 "  Hello, World!"
    }
    

以上就是在 Go 语言中移除字符串空白字符的方法。

字符串拆分

在 Java 中,你可以使用 split() 方法将一个字符串拆分成一个字符串数组,根据指定的分隔符进行拆分。

public class Main {
    public static void main(String[] args) {
        String str = "apple,banana,orange";
        String[] fruits = str.split(",");
        
        for (String fruit : fruits) {
            System.out.println(fruit);
        }
    }
}

在上面的示例中,我们定义了一个包含多个水果名称的字符串 str,然后使用 split() 方法将其根据逗号 , 进行拆分,并将结果存储在字符串数组 fruits 中。最后,我们使用 for 循环遍历数组,并逐个打印出拆分后的水果名称。

如果需要使用正则表达式作为分隔符,你可以使用 split(String regex) 方法,例如:

String str = "apple1banana2orange";
String[] fruits = str.split("\\d"); // 使用正则表达式 \d 匹配数字

在这个示例中,字符串 str 中包含数字 1 和 2,我们使用正则表达式 \d(表示匹配数字)作为分隔符,将字符串拆分成字符串数组。

这样就可以根据指定的分隔符或正则表达式对字符串进行拆分。

在 Go 语言中,你可以使用 strings.Split() 函数将一个字符串拆分成一个字符串切片,根据指定的分隔符进行拆分。

示例代码:

package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "apple,banana,orange"
	fruits := strings.Split(str, ",")
	
	for _, fruit := range fruits {
		fmt.Println(fruit)
	}
}

在上面的示例中,我们定义了一个包含多个水果名称的字符串 str,然后使用 strings.Split() 函数将其根据逗号 , 进行拆分,并将结果存储在字符串切片 fruits 中。然后,我们使用 for 循环遍历切片,并逐个打印出拆分后的水果名称。

如果需要使用正则表达式作为分隔符,你可以使用 regexp.Split() 函数

package main

import (
	"fmt"
	"regexp"
)

func main() {
	str := "apple1banana2orange"
	re := regexp.MustCompile("\\d") // 使用正则表达式 \d 匹配数字
	fruits := re.Split(str, -1)
	
	for _, fruit := range fruits {
		fmt.Println(fruit)
	}
}

在这个示例中,我们使用正则表达式 \d(表示匹配数字)作为分隔符,将字符串拆分成字符串切片。 -1 参数表示不限制拆分次数。

总结

Java 提供了丰富的字符串处理方法和类,例如 String 类和 StringBuilder 类,以及各种字符串操作方法如 split()、replace()、substring() 等。而Go 提供了 strings 包来进行字符串操作,其中包含了许多常用的字符串处理函数,如 Split()、Replace()、Substring() 等。其实并不需要我们记住所以,只需要用的时候查询即可。