1. StringTokenizerlớp học

Và bây giờ là một vài kịch bản phổ biến hơn liên quan đến làm việc với chuỗi. Làm thế nào để bạn chia một chuỗi thành nhiều phần? Có nhiều hướng khác nhau để làm điều đó.

split()phương pháp

Cách đầu tiên để tách một chuỗi thành nhiều phần là sử dụng split()phương thức. Một biểu thức chính quy xác định một chuỗi phân cách đặc biệt phải được chuyển thành đối số. Bạn sẽ tìm hiểu biểu thức chính quy là gì trong nhiệm vụ Đa luồng Java .

Ví dụ:

Mã số Kết quả
String str = "Good news everyone!";
String[] strings = str.split("ne");
System.out.println(Arrays.toString(strings));
Kết quả sẽ là một mảng gồm ba chuỗi:
["Good ", "ws everyo", "!"]

Đơn giản, nhưng đôi khi cách tiếp cận này là quá mức. Nếu có nhiều dấu phân cách (ví dụ: khoảng trắng, ký tự xuống dòng, tab, dấu chấm), thì bạn phải xây dựng một biểu thức chính quy khá phức tạp. Nó khó đọc và do đó khó sửa đổi.

StringTokenizerlớp học

Java có một lớp đặc biệt mà toàn bộ công việc của nó là chia một chuỗi thành các chuỗi con.

Lớp này không sử dụng các biểu thức chính quy: thay vào đó, bạn chỉ cần chuyển vào một chuỗi bao gồm các dấu phân cách. Ưu điểm của phương pháp này là nó không phá vỡ toàn bộ chuỗi thành từng mảnh cùng một lúc mà thay vào đó di chuyển từ đầu đến cuối từng bước một.

Lớp này có một hàm tạo và hai phương thức quan trọng. Chúng tôi chuyển cho hàm tạo một chuỗi mà chúng tôi chia thành các phần và một chuỗi bao gồm một tập hợp các ký tự phân cách.

phương pháp Sự miêu tả
String nextToken()
Trả về chuỗi con tiếp theo
boolean hasMoreTokens()
Kiểm tra xem có nhiều chuỗi con hơn không.

Lớp này phần nào gợi nhớ đến lớp Scanner, lớp này cũng có các phương thức nextLine()hasNextLine().

Bạn có thể tạo một StringTokenizerđối tượng bằng lệnh này:

StringTokenizer name = new StringTokenizer(string, delimiters);

Đâu stringlà chuỗi được chia thành các phần. Và delimiterslà một chuỗi và mỗi ký tự trong đó được coi là dấu phân cách. Ví dụ:

Mã số Đầu ra bảng điều khiển
String str = "Good news everyone!";

StringTokenizer tokenizer = new StringTokenizer(str,"ne");
while (tokenizer.hasMoreTokens())
{
   String token = tokenizer.nextToken();
   System.out.println(token);
}
Good 
ws 
v
ryo
!

Lưu ý rằng mỗi ký tự trong chuỗi được truyền dưới dạng chuỗi thứ hai cho StringTokenizerhàm tạo được coi là dấu phân cách.



2. String.format()phương thức và StringFormatterlớp

Một phương thức thú vị khác của lớp String là format().

Giả sử bạn có nhiều biến lưu trữ dữ liệu. Làm thế nào để bạn hiển thị chúng trên màn hình trong một dòng? Ví dụ: chúng tôi có một số dữ liệu (cột bên trái) và đầu ra mong muốn (cột bên phải):

Mã số Đầu ra bảng điều khiển
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;
User = {name: Amigo, age: 12 years, friend: Diego, weight: 200 kg.}

Mã của bạn có thể sẽ giống như thế này:

Mã chương trình
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;

System.out.println("User = {name: " + name + ", age:" + age + " years, friend: " + friend+", weight: " + weight + " kg.}");

Mã như vậy không phải là rất dễ đọc. Và nếu tên biến dài hơn, thì mã sẽ trở nên khó khăn hơn:

Mã chương trình

class User {
    ......
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public List<String> getFriends() {
        return friends;
    }

    public ExtraInformation getExtraInformation() {
        return extraInformation;
    }
}

User user = new User();

System.out.println("User = {name: " + user.getName() + ", age:" + user.getAge() + " years, friend: " + user.getFriends().get(0) + ", weight: " + user.getExtraInformation().getWeight() + " kg.}");

Không phải là rất dễ đọc, phải không?

Nhưng đây là một tình huống phổ biến trong các chương trình trong thế giới thực, vì vậy tôi muốn nói với bạn về cách viết mã này đơn giản và ngắn gọn hơn.

String.format

Lớp Chuỗi có một format()phương thức tĩnh: nó cho phép bạn chỉ định một mẫu để tập hợp một chuỗi có dữ liệu. Giao diện chung của lệnh như sau:

String name = String.format(pattern, parameters);

Ví dụ:

Mã số Kết quả
String.format("Age=%d, Name=%s", age, name);
Age=12, Name=Amigo
String.format("Width=%d, Height=%d", width, height);
Width=20, Height=10
String.format("Fullname=%s", name);
Fullname=Diego

Tham format()số đầu tiên của phương thức là một chuỗi định dạng chứa tất cả văn bản mong muốn cùng với các ký tự đặc biệt được gọi là định dạng định dạng (chẳng hạn như %d%s) ở những nơi bạn cần chèn dữ liệu.

Phương thức này format()thay thế các thông số này %s%dđịnh dạng bằng các tham số tuân theo chuỗi định dạng trong danh sách tham số. Nếu chúng ta muốn chèn một chuỗi, thì chúng ta viết %s. Nếu chúng ta muốn chèn một số, thì định dạng định dạng là %d. Ví dụ:

Mã số Kết quả
String s = String.format("a=%d, b=%d, c=%d", 1, 4, 3);
sbằng"a=1, b=4, c=3"

Đây là một danh sách ngắn các định dạng định dạng có thể được sử dụng bên trong chuỗi định dạng:

công cụ xác định Nghĩa
%s
String
%d
liên lạc: byte, short, int,long
%f
số thực: float,double
%b
boolean
%c
char
%t
Date
%%
%tính cách

Các bộ xác định này cho biết loại dữ liệu, nhưng cũng có các bộ xác định cho biết thứ tự của dữ liệu. Để lấy một đối số theo số của nó (việc đánh số bắt đầu từ một), bạn cần viết " " thay vì " ". Ví dụ:%1$d%d

Mã số Kết quả
String s = String.format("a=%3$d, b=%2$d, c=%d", 11, 12, 13);
sbằng"a=13, b=12, c=11"

%3$dsẽ nhận được đối số thứ 3, %2$dsẽ nhận được đối số thứ hai và %dsẽ nhận được đối số đầu tiên. Các bộ xác định định dạng %s%dtham chiếu đến các đối số bất kể các bộ xác định như %3$dhay%2$s



3. Bi-a dây

Mỗi chuỗi được chỉ định trong mã dưới dạng chuỗi ký tự được lưu trữ trong một vùng bộ nhớ được gọi là StringPoolkhi chương trình đang chạy. StringPoollà một mảng đặc biệt để lưu trữ các chuỗi. Mục đích của nó là để tối ưu hóa lưu trữ chuỗi:

Đầu tiên, các chuỗi được chỉ định trong mã phải được lưu trữ ở đâu đó, phải không? Mã bao gồm các lệnh, nhưng dữ liệu (đặc biệt là các chuỗi lớn) phải được lưu trữ trong bộ nhớ tách biệt với mã. Chỉ các tham chiếu đến các đối tượng chuỗi xuất hiện trong mã.

Thứ hai, tất cả các chuỗi ký tự giống hệt nhau chỉ được lưu trữ trong bộ nhớ một lần. Và đó chỉ là cách nó hoạt động. Khi mã lớp của bạn được tải bởi máy Java, tất cả các ký tự chuỗi sẽ được thêm vào StringPoolnếu chúng chưa có ở đó. Nếu chúng đã ở đó, thì chúng tôi chỉ cần sử dụng tham chiếu chuỗi từ tệp StringPool.

Theo đó, nếu bạn gán cùng một chữ cho một số Stringbiến trong mã của mình, thì các biến này sẽ chứa cùng một tham chiếu. Một chữ sẽ được thêm vào một StringPoollần duy nhất. Trong tất cả các trường hợp khác, mã sẽ nhận tham chiếu đến chuỗi đã được tải trong tệp StringPool.

Đây là cách nó hoạt động:

Mã số Làm việc với StringPool
String a = "Hello";
String b = "Hello";
String c = "Bye";
String[] pool = {"Hello", "Bye"};
a = pool[0];
b = pool[0];
c = pool[1];

Đó là lý do tại sao các biến absẽ lưu trữ các tham chiếu giống nhau.

intern()phương pháp

Và phần tốt nhất là bạn có thể lập trình thêm bất kỳ chuỗi nào vào tệp StringPool. Để làm điều này, bạn chỉ cần gọi phương thức Stringcủa biến intern().

Phương intern()thức sẽ thêm chuỗi vào StringPoolnếu nó chưa có ở đó và sẽ trả về một tham chiếu đến chuỗi trong tệp StringPool.

Nếu hai chuỗi giống hệt nhau được thêm vào phương thức StringPoolsử dụng intern(), phương thức này sẽ trả về cùng một tham chiếu. Điều này có thể được sử dụng để so sánh các chuỗi theo tham chiếu. Ví dụ:

Mã số Ghi chú
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);


false
String a = new String("Hello");
String b = new String("Hello");

String t1 = a.intern();
String t2 = b.intern();
System.out.println(a == b);
System.out.println(t1 == t2);





false
true

Bạn sẽ không thường xuyên sử dụng phương pháp này, nhưng mọi người lại thích hỏi về nó trong các cuộc phỏng vấn . Vì vậy, tốt hơn là biết về nó hơn là không biết.