So sánh các chuỗi trọng java năm 2024

Thật hợp lý khi kết quả vẫn như vậy (xét cho cùng, chúng tôi không thay đổi gì cả), nhưng giờ chúng tôi không hài lòng với nó! Quả thực, trong đời thực, phân tích DNA đảm bảo một trăm phần trăm rằng chúng ta đang đối mặt với những cặp song sinh. Nhưng chương trình và nhà điều hành của chúng tôi

public class Man {
   int dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1 == man2);
   }
}

4lại cho chúng tôi biết điều ngược lại. Làm cách nào chúng ta có thể thay đổi hành vi này và đảm bảo rằng nếu kết quả xét nghiệm ADN trùng khớp thì chương trình sẽ đưa ra kết quả chính xác? Với mục đích này, một phương thức đặc biệt đã được tạo trong Java - Equals() .

Phương thức Equals() trong Java

Giống như phương thức

public class Man {
   int dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1 == man2);
   }
}

9mà chúng ta đã thảo luận trước đó, Equals() thuộc về lớp,


false

0lớp quan trọng nhất trong Java, mà tất cả các lớp khác đều bắt nguồn từ đó. Tuy nhiên, bản thân Equals() sẽ không thay đổi hành vi của chương trình theo bất kỳ cách nào:

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

Đầu ra của bảng điều khiển:


false

Kết quả hoàn toàn giống nhau, vậy tại sao lại cần phương pháp này? :/ Thật đơn giản. Thực tế là bây giờ chúng tôi đã sử dụng phương pháp này vì nó được triển khai trong chính lớp đó


false

0. Và nếu chúng ta đi vào mã lớp


false

0và xem phương thức này được triển khai như thế nào và nó làm gì, chúng ta sẽ thấy:

public boolean equals(Object obj) {
   return (this == obj);
}

Đây là lý do tại sao hành vi của chương trình của chúng tôi không thay đổi! Bên trong phương thức Equals() của lớp


false

0có cùng một so sánh tham chiếu tương tự,

public class Man {
   int dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1 == man2);
   }
}

4. Nhưng mẹo của phương pháp này là chúng ta có thể ghi đè lên nó. Ghi đè có nghĩa là viết phương thức Equals() của riêng bạn trong lớp của chúng ta


false

5và làm cho nó hoạt động theo cách chúng ta muốn! Bây giờ chúng tôi không hài lòng rằng


false

6về cơ bản, việc kiểm tra cũng thực hiện giống như


false

7. Đây là những gì chúng ta sẽ làm trong tình huống này:

public class Man {
   int dnaCode;
   public boolean equals(Man man) {
       return this.dnaCode ==  man.dnaCode;
   }
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1.equals(man2));
   }
}

Đầu ra của bảng điều khiển:


true

Một kết quả hoàn toàn khác! Bằng cách viết phương thức Equals() của riêng mình thay vì phương thức tiêu chuẩn, chúng ta đã đạt được hành vi đúng: bây giờ nếu hai người có cùng mã DNA, chương trình sẽ cho chúng ta biết: “Phân tích DNA cho thấy họ là anh em sinh đôi” và trả về giá trị true! Bằng cách ghi đè phương thức bằng() trong các lớp của mình, bạn có thể dễ dàng tạo logic so sánh đối tượng cần thiết. Chúng tôi chỉ đề cập đến việc so sánh các đối tượng một cách chung chung. Chúng tôi vẫn sẽ có một bài giảng lớn riêng về chủ đề này ở phía trước (bạn có thể đọc nhanh ngay bây giờ nếu quan tâm).

So sánh chuỗi trong Java - So sánh chuỗi

Tại sao chúng ta xử lý việc so sánh chuỗi một cách riêng biệt với mọi thứ khác? Thực ra, các dòng trong lập trình là một câu chuyện hoàn toàn khác. Thứ nhất, nếu bạn xem xét tất cả các chương trình Java do loài người viết ra, khoảng 25% đối tượng trong đó được tạo thành từ chúng. Vì vậy, chủ đề này là rất quan trọng. Thứ hai, quá trình so sánh các chuỗi thực sự khá khác biệt so với các đối tượng khác. Hãy xem một ví dụ đơn giản:

public class Main {
   public static void main(String[] args) {
       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}

Đầu ra của bảng điều khiển:


false

Nhưng tại sao lại sai? Các dòng giống hệt nhau, từng chữ một :/ Bạn có thể cho rằng: điều này là do toán tử

public class Man {
   int dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1 == man2);
   }
}

4 so sánh các tham chiếu! Rốt cuộc,


false

9họ

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

0có địa chỉ khác nhau trong bộ nhớ. Nếu ý nghĩ này xảy ra với bạn, thì hãy làm lại ví dụ của chúng ta:


false

1

Bây giờ chúng ta cũng có 2 link nhưng kết quả lại ngược lại:


true

Hoàn toàn bối rối? :) Hãy tìm ra nó. Toán tử

public class Man {
   int dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1 == man2);
   }
}

4thực sự so sánh các địa chỉ trong bộ nhớ. Quy tắc này luôn hoạt động và không cần phải nghi ngờ gì về nó. Điều này có nghĩa là nếu

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

2trả về true thì hai chuỗi này có cùng địa chỉ trong bộ nhớ. Và thực sự là như vậy! Đã đến lúc làm quen với một vùng bộ nhớ đặc biệt để lưu trữ chuỗi - nhóm chuỗi (

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

  1. So sánh các chuỗi trọng java năm 2024
    Nhóm chuỗi là vùng lưu trữ tất cả các giá trị chuỗi mà bạn tạo trong chương trình của mình. Nó được tạo ra để làm gì? Như đã đề cập trước đó, chuỗi chiếm một phần rất lớn trong tất cả các đối tượng. Trong bất kỳ chương trình lớn nào, rất nhiều dòng được tạo ra. Để tiết kiệm bộ nhớ, đây là điều cần thiết

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

4- một dòng có văn bản bạn cần được đặt ở đó và trong tương lai, các liên kết mới được tạo sẽ đề cập đến cùng một vùng bộ nhớ, không cần phải phân bổ thêm bộ nhớ mỗi lần. Mỗi lần bạn viết

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

5, chương trình sẽ kiểm tra xem có dòng nào có văn bản như vậy trong nhóm chuỗi hay không. Nếu có, một cái mới sẽ không được tạo ra. Và liên kết mới sẽ trỏ đến cùng một địa chỉ trong nhóm chuỗi nơi chuỗi này được lưu trữ. Vì vậy, khi viết chương trình


false

3

liên kết

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

0trỏ chính xác đến cùng một vị trí với


false

9. Lệnh đầu tiên đã tạo một dòng mới trong nhóm chuỗi với văn bản chúng ta cần và khi đến dòng thứ hai, nó chỉ đơn giản đề cập đến cùng một vùng bộ nhớ như


false

9. Bạn có thể viết thêm ít nhất 500 dòng với cùng một văn bản, kết quả sẽ không thay đổi. Dừng lại. Nhưng tại sao ví dụ này không có tác dụng với chúng ta trước đây?

public class Main {
   public static void main(String[] args) {
       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}

Tôi nghĩ, bằng trực giác, bạn đã đoán được lý do là gì :) Hãy thử đoán trước khi đọc tiếp. Bạn có thể thấy hai dòng này được tạo ra khác nhau. Một là với sự trợ giúp của người vận hành

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

9, và thứ hai là không có nó. Đây chính xác là lý do. Toán tử mới khi tạo một đối tượng sẽ buộc phải cấp phát một vùng mới trong bộ nhớ cho đối tượng đó . Và dòng được tạo bằng

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

9, không kết thúc bằng

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

4: nó trở thành một đối tượng riêng biệt, ngay cả khi văn bản của nó hoàn toàn giống với cùng một dòng từ

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

4'a. Đó là, nếu chúng ta viết đoạn mã sau:


false

5

Trong bộ nhớ, nó sẽ trông như thế này:

So sánh các chuỗi trọng java năm 2024
Và mỗi khi một đối tượng mới được tạo,
public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

9một vùng mới sẽ được cấp phát trong bộ nhớ, ngay cả khi văn bản bên trong các dòng mới giống nhau! Có vẻ như chúng ta đã sắp xếp xong toán tử

public class Man {
   int dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1 == man2);
   }
}

4, nhưng còn người bạn mới của chúng ta - phương thức Equals() thì sao?


false

6

Đầu ra của bảng điều khiển:


true

Hấp dẫn. Chúng tôi biết chính xác những gì


false

9và

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

0trỏ đến các khu vực khác nhau trong bộ nhớ. Tuy nhiên, phương thức bằng() nói rằng chúng bằng nhau. Tại sao? Bạn có nhớ ở trên chúng ta đã nói rằng phương thức Equals() có thể được ghi đè trong lớp của bạn để nó so sánh các đối tượng theo cách bạn cần không? Đó là những gì họ đã làm với lớp học


false

7. Nó có một phương thức bằng() bị ghi đè. Và nó không so sánh các liên kết mà là chuỗi ký tự trong chuỗi. Và nếu văn bản trong các chuỗi giống nhau, thì chúng được tạo ra như thế nào và chúng được lưu trữ ở đâu không quan trọng: trong nhóm chuỗi hoặc trong một vùng bộ nhớ riêng. Kết quả so sánh sẽ đúng. Nhân tiện, Java cho phép bạn so sánh chính xác các chuỗi theo cách không phân biệt chữ hoa chữ thường. Trong tình huống bình thường, nếu bạn viết một trong các dòng, chẳng hạn như viết hoa, kết quả so sánh sẽ sai:


false

8

Đầu ra của bảng điều khiển:


false

Trong trường hợp này, lớp


false

7có một phương thức


false

9. Nếu điều chính trong so sánh của bạn là chuỗi các ký tự cụ thể chứ không phải trường hợp của chúng, bạn có thể sử dụng nó. Ví dụ: điều này sẽ hữu ích khi so sánh hai địa chỉ email:

public class Man {
   int dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1 == man2);
   }
}

0

Trong trường hợp này, rõ ràng là chúng ta đang nói về cùng một địa chỉ nên việc sử dụng phương pháp này


false

9sẽ là quyết định đúng đắn.

Phương thức String.intern()

Lớp này


false

7có một phương thức phức tạp khác -

public boolean equals(Object obj) {
   return (this == obj);
}

2; Phương thức này

public boolean equals(Object obj) {
   return (this == obj);
}

2hoạt động trực tiếp với

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

4'om. Nếu bạn gọi một phương thức

public boolean equals(Object obj) {
   return (this == obj);
}

2trên một chuỗi, nó:

  • Nhìn xem có chuỗi nào có văn bản này trong nhóm chuỗi không
  • Nếu có, trả về một liên kết đến nó trong nhóm
  • Nếu không, nó sẽ đặt một dòng có văn bản này vào nhóm chuỗi và trả về một liên kết tới nó.

Bằng cách áp dụng phương thức này

public boolean equals(Object obj) {
   return (this == obj);
}

2cho tham chiếu chuỗi được tạo thông qua new, chúng ta có thể so sánh nó với tham chiếu chuỗi từ

public class Man {
   String dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = "111122223333";
       Man man2 = new Man();
       man2.dnaCode = "111122223333";
       System.out.println(man1.equals(man2));
   }
}

4'a qua

public class Man {
   int dnaCode;
   public static void main(String[] args) {
       Man man1 = new Man();
       man1.dnaCode = 1111222233;
       Man man2 = new Man();
       man2.dnaCode = 1111222233;
       System.out.println(man1 == man2);
   }
}

4.