Thuật ngữ “dạng chuẩn” hoặc “dạng biểu diễn chuẩn” trong Java có nghĩa là gì?


90

Tôi đã thường xuyên nghe thấy thuật ngữ này được sử dụng, nhưng tôi chưa bao giờ thực sự hiểu nó.

Nó có nghĩa là gì, và bất cứ ai có thể cho một số ví dụ / chỉ cho tôi một số liên kết?

CHỈNH SỬA: Cảm ơn mọi người đã trả lời. Bạn cũng có thể cho tôi biết cách biểu diễn chính tắc hữu ích như thế nào trong hiệu suất bằng (), như đã nêu trong Java hiệu quả không?

Câu trả lời:


56

Wikipedia chỉ ra thuật ngữ Canonicalization .

Quy trình chuyển đổi dữ liệu có nhiều hơn một biểu diễn có thể thành một biểu diễn chính tắc "chuẩn". Điều này có thể được thực hiện để so sánh các biểu diễn khác nhau về sự tương đương, đếm số lượng cấu trúc dữ liệu riêng biệt, để cải thiện hiệu quả của các thuật toán khác nhau bằng cách loại bỏ các phép tính lặp lại hoặc để có thể áp đặt một thứ tự sắp xếp có ý nghĩa.

Các Unicode dụ làm ý nghĩa nhất đối với tôi:

Các mã hóa có độ dài thay đổi trong tiêu chuẩn Unicode, cụ thể là UTF-8, có nhiều hơn một mã hóa khả thi cho hầu hết các ký tự phổ biến. Điều này làm cho việc xác thực chuỗi phức tạp hơn, vì mọi mã hóa có thể có của mỗi ký tự chuỗi phải được xem xét. Việc triển khai phần mềm không xem xét tất cả các mã hóa ký tự có nguy cơ chấp nhận các chuỗi được coi là không hợp lệ trong thiết kế ứng dụng, điều này có thể gây ra lỗi hoặc cho phép tấn công. Giải pháp là cho phép một mã hóa duy nhất cho mỗi ký tự. Canonicalization sau đó là quá trình dịch mọi ký tự chuỗi sang bảng mã được phép duy nhất của nó. Một giải pháp thay thế dành cho phần mềm để xác định xem một chuỗi có được chuẩn hóa hay không và sau đó từ chối nó nếu không. Trong trường hợp này, trong ngữ cảnh máy khách / máy chủ, việc chuẩn hóa sẽ là trách nhiệm của máy khách.

Tóm lại, một dạng biểu diễn tiêu chuẩn cho dữ liệu. Từ biểu mẫu này, bạn có thể chuyển đổi sang bất kỳ hình thức biểu diễn nào mà bạn có thể cần.


64

Tôi tin rằng có hai cách sử dụng liên quan của canonical: biểu mẫu và phiên bản.

Một hình thức kinh điển phương tiện mà giá trị của một loại hình cụ thể của tài nguyên có thể được mô tả hay thể hiện theo nhiều cách, và là một trong những cách được chọn là hình thức kinh điển được ưa chuộng. (Biểu mẫu đó được chuẩn hóa , giống như sách đã đưa nó vào kinh thánh, còn các biểu mẫu khác thì không.) Một ví dụ cổ điển về biểu mẫu chuẩn là các đường dẫn trong hệ thống tệp phân cấp, trong đó một tệp duy nhất có thể được tham chiếu theo một số cách :

myFile.txt                                   # in current working dir
../conf/myFile.txt                           # relative to the CWD
/apps/tomcat/conf/myFile.txt                 # absolute path using symbolic links
/u1/local/apps/tomcat-5.5.1/conf/myFile.txt  # absolute path with no symlinks

Định nghĩa cổ điển về biểu diễn chuẩn của tệp đó sẽ là đường dẫn cuối cùng. Với các đường dẫn cục bộ hoặc tương đối, bạn không thể xác định toàn cục tài nguyên mà không có thông tin ngữ cảnh. Với các đường dẫn tuyệt đối, bạn có thể xác định tài nguyên, nhưng không thể biết liệu hai đường dẫn có tham chiếu đến cùng một thực thể hay không. Với hai hoặc nhiều đường dẫn được chuyển đổi sang dạng chuẩn, bạn có thể thực hiện tất cả những việc trên, đồng thời xác định xem hai tài nguyên có giống nhau hay không, nếu điều đó quan trọng đối với ứng dụng của bạn (giải quyết vấn đề răng cưa ).

Lưu ý rằng dạng chuẩn của tài nguyên không phải là chất lượng của chính dạng cụ thể đó; có thể có nhiều dạng chuẩn có thể có cho một loại nhất định như đường dẫn tệp (giả sử, về mặt từ vựng trước hết là đường dẫn tuyệt đối có thể có). Một biểu mẫu chỉ được chọn làm biểu mẫu chuẩn vì một lý do ứng dụng cụ thể, hoặc có thể tùy ý để mọi người nói cùng một ngôn ngữ.

Buộc các đối tượng vào các phiên bản chính tắc của chúng là cùng một ý tưởng cơ bản, nhưng thay vì xác định một đại diện "tốt nhất" của tài nguyên, nó tùy ý chọn một phiên bản của một lớp cá thể có cùng "nội dung" với tham chiếu chính tắc, sau đó chuyển đổi tất cả các tham chiếu tới các đối tượng tương đương để sử dụng một phiên bản chuẩn.

Đây có thể được sử dụng như một kỹ thuật để tối ưu hóa cả thời gian và không gian. Nếu có nhiều bản sao của các đối tượng tương đương trong một ứng dụng, thì bằng cách buộc tất cả chúng phải được giải quyết dưới dạng bản chính tắc duy nhất của một giá trị cụ thể, bạn có thể loại bỏ tất cả trừ một trong mỗi giá trị, tiết kiệm không gian và có thể là thời gian vì bây giờ bạn có thể so sánh những giá trị có danh tính tham chiếu (==) trái ngược với tương đương đối tượng ( equals()phương thức).

Một ví dụ cổ điển về tối ưu hóa hiệu suất với các phiên bản chuẩn là thu gọn các chuỗi có cùng nội dung. Việc gọi String.intern()trên hai chuỗi có cùng chuỗi ký tự được đảm bảo trả về cùng một đối tượng Chuỗi chính tắc cho văn bản đó. Nếu bạn chuyển tất cả các chuỗi của mình qua bộ chuẩn hóa đó, bạn biết các chuỗi tương đương thực sự là các tham chiếu đối tượng giống hệt nhau, tức là bí danh

Các kiểu enum trong Java 5.0+ buộc tất cả các phiên bản của một giá trị enum cụ thể phải sử dụng cùng một phiên bản chuẩn trong một máy ảo, ngay cả khi giá trị được tuần tự hóa và giải mã hóa. Đó là lý do tại sao bạn có thể sử dụng if (day == Days.SUNDAY)với impunity trong java nếu Dayslà một kiểu enum. Làm điều này cho các lớp học của riêng bạn chắc chắn là có thể, nhưng hãy cẩn thận. Đọc Java hiệu quả của Josh Bloch để biết chi tiết và lời khuyên.


31

Một ví dụ tốt để hiểu "biểu mẫu / biểu diễn chuẩn" là xem định nghĩa kiểu dữ liệu lược đồ XML của "boolean":

  • "đại diện từ vựng" của boolean có thể là một trong số: {true, false, 1, 0}trong khi
  • "đại diện chính tắc" chỉ có thể là một trong số {true, false}

Về bản chất, điều này có nghĩa là

  • "true""1"được ánh xạ tới đại diện chính tắc. "true"
  • "false""0"được ánh xạ tới đại diện hợp lệ."false"

xem định nghĩa kiểu dữ liệu lược đồ XML w3 cho boolean


28

Từ "canonical" chỉ là một từ đồng nghĩa với "tiêu chuẩn" hoặc "thông thường". Nó không có bất kỳ ý nghĩa nào dành riêng cho Java.


3
canonical có nghĩa phong phú hơn IMO tiêu chuẩn hoặc thông thường.
mực,

20

giảm xuống dạng đơn giản nhất và quan trọng nhất mà không làm mất tính tổng quát


5

Một cách dễ nhớ đó là cách “canonical” được dùng trong giới thần học, sự thật kinh điển là sự thật nên nếu hai người tìm ra thì họ đã tìm thấy cùng một sự thật. Tương tự với phiên bản chuẩn. Nếu bạn nghĩ rằng bạn đã tìm thấy hai trong số họ (tức là a.equals(b)) bạn thực sự chỉ có một (tức là a == b). Vì vậy, bình đẳng bao hàm sự đồng nhất trong trường hợp đối tượng chính tắc.

Bây giờ để so sánh. Bây giờ bạn có lựa chọn sử dụng a==b hoặc a.equals(b) , vì chúng sẽ tạo ra cùng một câu trả lời trong trường hợp phiên bản chuẩn nhưng a == b là so sánh của tham chiếu (JVM có thể so sánh hai số cực kỳ nhanh chóng vì chúng chỉ là hai mẫu 32 bit được so sánh để a.equals(b)đó là một phương pháp gọi và liên quan đến chi phí hơn.


2

Một ví dụ điển hình khác có thể là: bạn có một lớp hỗ trợ việc sử dụng các tọa độ Cartesian (x, y, z), hình cầu (r, theta, phi) và trụ (r, phi, z). Đối với mục đích thiết lập bình đẳng (phương pháp bằng), bạn có thể muốn chuyển đổi tất cả các biểu diễn thành một biểu diễn "chính tắc" mà bạn chọn, ví dụ như tọa độ cầu. (Hoặc có thể bạn muốn làm điều này nói chung - tức là sử dụng một đại diện bên trong.) Tôi không phải là chuyên gia, nhưng điều này đã xảy ra với tôi như một ví dụ cụ thể tốt.


0

đại diện chính tắc có nghĩa là xem ký tự theo kiểu khác, ví dụ nếu tôi viết chữ A nghĩa là người khác có thể viết chữ A theo kiểu khác :)

Đây là theo LĨNH VỰC NHẬN BIẾT ĐẶC TRƯNG QUANG


0

Biểu mẫu chuẩn có nghĩa là một biểu diễn duy nhất tự nhiên của phần tử


0

Cả hai câu hỏi của OP về biểu mẫu chuẩn và cách nó có thể cải thiện hiệu suất của equalsphương pháp đều có thể được trả lời bằng cách mở rộng ví dụ được cung cấp trong Java hiệu quả.

Hãy xem xét lớp sau:

public final class CaseInsensitiveString {

  private final String s;

  public CaseInsensitiveString(String s) {
    this.s = Objects.requireNonNull(s);
  }

  @Override 
  public boolean equals(Object o) {
    return o instanceof CaseInsensitiveString && ((CaseInsensitiveString) o).s.equalsIgnoreCase(s);
  }
}

Các equalsphương pháp trong ví dụ này đã được thêm vào chi phí bằng cách sử dụng String's equalsIgnoreCasephương pháp. Như đã đề cập trong văn bản

bạn có thể muốn lưu trữ một dạng chuẩn của trường để phương thức bằng có thể thực hiện một phép so sánh chính xác rẻ tiền trên các dạng chuẩn thay vì so sánh không chuẩn tốn kém hơn.

Joshua Bloch có ý gì khi nói hình thức chuẩn ? Chà, tôi nghĩ câu trả lời ngắn gọn của Dónal là rất thích hợp. Chúng ta có thể lưu trữ trường cơ bản Stringtrong CaseInsensitiveStringví dụ theo cách chuẩn , có lẽ là dạng viết hoa của String. Bây giờ, bạn có thể tham chiếu biểu mẫu chuẩn này của CaseInsensitiveString, biến thể viết hoa của nó và thực hiện đánh giá rẻ trong các phương thức equalsvà của bạn hashcode.


0

Dữ liệu Canonical trong RDBMS, Dữ liệu Đồ thị;
Hãy coi như là "Chuẩn hóa" hoặc "Dạng chuẩn" của dữ liệu trong RDBMS. Dữ liệu giống nhau tồn tại trong các bảng khác nhau, được biểu thị bằng một số nhận dạng duy nhất và ánh xạ nó trong các bảng khác nhau.
hoặc
Nghĩ về một dạng dữ liệu duy nhất trong Cơ sở dữ liệu đồ thị được biểu diễn trong nhiều bộ ba.

Lợi ích chính của nó là làm cho Dml (Thao tác dữ liệu) hiệu quả hơn vì bạn có thể nâng cấp (chèn / cập nhật) chỉ một giá trị thay vì nhiều giá trị.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.