คำว่า“ canonical form” หรือ“ canonical representation” ใน Java หมายถึงอะไร


91

ฉันมักจะได้ยินคำนี้ถูกใช้ แต่ฉันไม่เคยเข้าใจจริงๆ

หมายความว่าอย่างไรและใครช่วยยกตัวอย่าง / ชี้ให้ฉันดูลิงก์ได้บ้าง

แก้ไข: ขอบคุณทุกคนสำหรับการตอบกลับ คุณช่วยบอกฉันได้ไหมว่าการแสดงตามรูปแบบบัญญัติมีประโยชน์ในประสิทธิภาพเท่ากับ () ตามที่ระบุไว้ใน Effective Java อย่างไร

คำตอบ:


58

วิกิพีเดียชี้ไปที่ระยะการแปลงข้อมูล

กระบวนการในการแปลงข้อมูลที่มีการแทนค่าที่เป็นไปได้มากกว่าหนึ่งรายการให้เป็นการแสดงตามรูปแบบบัญญัติ "มาตรฐาน" สิ่งนี้สามารถทำได้เพื่อเปรียบเทียบการนำเสนอที่แตกต่างกันสำหรับความเท่าเทียมกันเพื่อนับจำนวนโครงสร้างข้อมูลที่แตกต่างกันเพื่อปรับปรุงประสิทธิภาพของอัลกอริทึมต่างๆโดยการกำจัดการคำนวณซ้ำ ๆ หรือเพื่อให้สามารถกำหนดลำดับการเรียงลำดับที่มีความหมายได้

Unicodeตัวอย่างเช่นทำให้ความรู้สึกมากที่สุดกับฉัน:

การเข้ารหัสความยาวตัวแปรในมาตรฐาน Unicode โดยเฉพาะ UTF-8 มีการเข้ารหัสที่เป็นไปได้มากกว่าหนึ่งตัวสำหรับอักขระทั่วไป สิ่งนี้ทำให้การตรวจสอบความถูกต้องของสตริงมีความซับซ้อนมากขึ้นเนื่องจากต้องพิจารณาการเข้ารหัสที่เป็นไปได้ของอักขระสตริงแต่ละตัว การใช้งานซอฟต์แวร์ที่ไม่พิจารณาการเข้ารหัสอักขระทั้งหมดจะเสี่ยงต่อการยอมรับสตริงที่ถือว่าไม่ถูกต้องในการออกแบบแอปพลิเคชันซึ่งอาจทำให้เกิดข้อบกพร่องหรือทำให้เกิดการโจมตี วิธีแก้ปัญหาคืออนุญาตให้มีการเข้ารหัสเพียงครั้งเดียวสำหรับแต่ละอักขระ จากนั้น Canonicalization เป็นกระบวนการในการแปลอักขระสตริงทุกตัวเป็นการเข้ารหัสเดียวที่อนุญาต อีกทางเลือกหนึ่งคือให้ซอฟต์แวร์ตรวจสอบว่าสตริงเป็นแบบบัญญัติหรือไม่จากนั้นจึงปฏิเสธหากไม่ใช่ ในกรณีนี้ในบริบทไคลเอนต์ / เซิร์ฟเวอร์การบัญญัติศัพท์จะเป็นความรับผิดชอบของไคลเอ็นต์

โดยสรุปรูปแบบมาตรฐานของการแสดงข้อมูล จากแบบฟอร์มนี้คุณสามารถแปลงเป็นตัวแทนตามที่คุณต้องการได้


64

ฉันเชื่อว่ามีการใช้รูปแบบบัญญัติที่เกี่ยวข้องสองประการ: แบบฟอร์มและอินสแตนซ์

ที่ยอมรับรูปแบบหมายถึงว่าค่าของประเภทเฉพาะของทรัพยากรที่สามารถอธิบายหรือแสดงในหลายวิธีและหนึ่งในวิธีเหล่านั้นได้รับการแต่งตั้งเป็นรูปแบบที่เป็นที่ยอมรับได้รับการสนับสนุน (รูปแบบนั้นเป็นรูปแบบบัญญัติเช่นเดียวกับหนังสือที่สร้างเป็นพระคัมภีร์และรูปแบบอื่น ๆ ไม่ได้) ตัวอย่างคลาสสิกของรูปแบบบัญญัติคือพา ธ ในระบบไฟล์แบบลำดับชั้นซึ่งไฟล์เดียวสามารถอ้างอิงได้หลายวิธี :

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

คำจำกัดความคลาสสิกของการแสดงตามรูปแบบบัญญัติของไฟล์นั้นจะเป็นพา ธ สุดท้าย ด้วยเส้นทางท้องถิ่นหรือสัมพัทธ์คุณไม่สามารถระบุทรัพยากรทั่วโลกโดยไม่มีข้อมูลบริบท ด้วยพา ธ สัมบูรณ์คุณสามารถระบุทรัพยากรได้ แต่ไม่สามารถบอกได้ว่าสองเส้นทางอ้างถึงเอนทิตีเดียวกันหรือไม่ ด้วยเส้นทางสองเส้นทางขึ้นไปที่แปลงเป็นรูปแบบบัญญัติคุณสามารถดำเนินการทั้งหมดข้างต้นรวมทั้งตรวจสอบว่าทรัพยากรสองรายการเหมือนกันหรือไม่หากมีความสำคัญต่อแอปพลิเคชันของคุณ (แก้ปัญหานามแฝง )

โปรดทราบว่ารูปแบบมาตรฐานของทรัพยากรไม่ใช่คุณภาพของรูปแบบนั้นเอง อาจมีรูปแบบบัญญัติที่เป็นไปได้หลายรูปแบบสำหรับประเภทที่กำหนดเช่นเส้นทางไฟล์ (เช่นตามศัพท์เป็นอันดับแรกของพา ธ สัมบูรณ์ที่เป็นไปได้ทั้งหมด) รูปแบบหนึ่งถูกเลือกเป็นเพียงรูปแบบบัญญัติเพื่อเหตุผลในการใช้งานเฉพาะหรืออาจจะโดยพลการเพื่อให้ทุกคนพูดภาษาเดียวกัน

การบังคับให้ออบเจ็กต์เป็นอินสแตนซ์ตามรูปแบบบัญญัติเป็นแนวคิดพื้นฐานเดียวกัน แต่แทนที่จะพิจารณาการแสดงทรัพยากรที่ "ดีที่สุด" อย่างใดอย่างหนึ่งโดยพลการจะเลือกอินสแตนซ์ของคลาสของอินสแตนซ์ที่มี "เนื้อหา" เดียวกับการอ้างอิงตามรูปแบบบัญญัติโดยพลการแล้วแปลงการอ้างอิงทั้งหมด กับวัตถุที่เทียบเท่าเพื่อใช้อินสแตนซ์ Canonical เดียว

ซึ่งสามารถใช้เป็นเทคนิคในการเพิ่มประสิทธิภาพทั้งเวลาและพื้นที่ หากมีหลายอินสแตนซ์ของออบเจ็กต์ที่เทียบเท่ากันในแอปพลิเคชันจากนั้นการบังคับให้พวกเขาทั้งหมดได้รับการแก้ไขเป็นอินสแตนซ์มาตรฐานเดียวของค่าเฉพาะคุณสามารถกำจัดค่าทั้งหมดยกเว้นค่าใดค่าหนึ่งเพื่อประหยัดพื้นที่และอาจใช้เวลาเนื่องจากคุณสามารถเปรียบเทียบได้แล้ว ค่าเหล่านั้นที่มีเอกลักษณ์อ้างอิง (==) ซึ่งตรงข้ามกับความเท่าเทียมกันของวัตถุ ( equals()วิธีการ)

ตัวอย่างคลาสสิกของการเพิ่มประสิทธิภาพด้วยอินสแตนซ์ Canonical คือการยุบสตริงที่มีเนื้อหาเดียวกัน การเรียกString.intern()ใช้สองสตริงที่มีลำดับอักขระเดียวกันจะรับประกันว่าจะส่งคืนอ็อบเจ็กต์สตริงที่เป็นที่ยอมรับเดียวกันสำหรับข้อความนั้น หากคุณส่งสตริงทั้งหมดของคุณผ่าน canonicalizer นั้นคุณจะรู้ว่าสตริงที่เทียบเท่ากันนั้นแท้จริงแล้วการอ้างอิงอ็อบเจ็กต์เหมือนกันนั่นคือนามแฝง

ประเภท enum ใน Java 5.0+ บังคับให้อินสแตนซ์ทั้งหมดของค่า enum เฉพาะใช้อินสแตนซ์ Canonical เดียวกันภายใน VM แม้ว่าค่าจะเป็นอนุกรมและ deserialized ก็ตาม นั่นคือเหตุผลที่คุณสามารถใช้if (day == Days.SUNDAY)กับการไม่ต้องรับโทษใน java ได้หากDaysเป็นประเภท enum การทำเช่นนี้สำหรับชั้นเรียนของคุณเป็นไปได้อย่างแน่นอน แต่ต้องระวัง อ่านEffective Javaโดย Josh Bloch สำหรับรายละเอียดและคำแนะนำ


32

ตัวอย่างที่ดีในการทำความเข้าใจ "รูปแบบ / การเป็นตัวแทนที่ยอมรับ" คือการดูนิยามประเภทข้อมูลสคีมา XML ของ "บูลีน":

  • "การแสดงศัพท์" ของบูลีนสามารถเป็นหนึ่งใน: {true, false, 1, 0}ในขณะที่
  • "การแสดงตามรูปแบบบัญญัติ" สามารถเป็นได้เพียงหนึ่งใน {true, false}

โดยพื้นฐานแล้วนี่หมายความว่า

  • "true"และ"1"ได้รับการแมปกับตัวแทนมาตรฐาน "true"และ
  • "false"และ"0"ได้รับการแมปกับตัวแทนตามหลักบัญญัติ"false"

ดูข้อกำหนดประเภทข้อมูลสคีมา w3 XML สำหรับบูลีน


28

คำว่า "บัญญัติ" เป็นเพียงคำพ้องความหมายของ "มาตรฐาน" หรือ "ปกติ" มันไม่มีความหมายเฉพาะ Java


3
บัญญัติมีความหมายที่สมบูรณ์กว่า IMO มาตรฐานหรือปกติ
ปลาหมึก

21

ลดลงเป็นรูปแบบที่ง่ายที่สุดและสำคัญที่สุดโดยไม่สูญเสียลักษณะทั่วไป


5

วิธีง่ายๆในการจำมันคือวิธีที่ "บัญญัติ" ใช้ในวงการศาสนศาสตร์ความจริงตามบัญญัติคือความจริงที่แท้จริงดังนั้นหากคนสองคนพบว่าพวกเขาได้พบความจริงเดียวกัน เช่นเดียวกับอินสแตนซ์ตามรูปแบบบัญญัติ หากคุณคิดว่าคุณพบสองคน (เช่นa.equals(b)) คุณมีเพียงหนึ่ง (เช่นa == b) ความเท่าเทียมกันจึงแสดงถึงเอกลักษณ์ในกรณีของวัตถุบัญญัติ

ตอนนี้สำหรับการเปรียบเทียบ ตอนนี้คุณมีทางเลือกในการใช้a==b หรือ a.equals(b)เนื่องจากจะให้คำตอบเดียวกันในกรณีของอินสแตนซ์มาตรฐาน แต่ a == b เป็นการเปรียบเทียบการอ้างอิง (JVM สามารถเปรียบเทียบตัวเลขสองจำนวนได้อย่างรวดเร็วมากเนื่องจากเป็นเพียงรูปแบบ 32 บิตสองรูปแบบ ไปa.equals(b)ซึ่งเป็นวิธีการเรียกและเกี่ยวข้องกับค่าใช้จ่ายมากขึ้น


2

อีกตัวอย่างหนึ่งที่ดีอาจ ได้แก่ คุณมีคลาสที่รองรับการใช้คาร์ทีเซียน (x, y, z), ทรงกลม (r, theta, phi) และพิกัดทรงกระบอก (r, phi, z) เพื่อจุดประสงค์ในการสร้างความเท่าเทียมกัน (วิธีการเท่ากับ) คุณอาจต้องการแปลงการแสดงทั้งหมดเป็นการแสดง "บัญญัติ" ที่คุณเลือกเช่นพิกัดทรงกลม (หรือบางทีคุณอาจต้องการทำสิ่งนี้โดยทั่วไป - เช่นใช้การแสดงภายในหนึ่งรายการ) ฉันไม่ใช่ผู้เชี่ยวชาญ แต่สิ่งนี้เกิดขึ้นกับฉันเนื่องจากอาจเป็นตัวอย่างที่ดี


0

การแสดงตามรูปแบบบัญญัติหมายถึงการดูตัวอักษรในลักษณะที่แตกต่างกันเช่นถ้าฉันเขียนตัวอักษร A หมายความว่าบุคคลอื่นอาจเขียนตัวอักษร A ในรูปแบบที่แตกต่างกัน :)

เป็นไปตาม OPTICAL CHARACTER RECOGNITION FIELD


0

รูปแบบบัญญัติหมายถึงการแสดงองค์ประกอบที่เป็นเอกลักษณ์ตามธรรมชาติ


0

คำถามของ OP เกี่ยวกับรูปแบบบัญญัติและวิธีการปรับปรุงประสิทธิภาพของequalsวิธีนี้สามารถตอบได้โดยการขยายตัวอย่างที่ให้ไว้ใน Effective Java

พิจารณาคลาสต่อไปนี้:

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);
  }
}

equalsวิธีการในตัวอย่างนี้ได้มีการเพิ่มค่าใช้จ่ายโดยใช้String's equalsIgnoreCaseวิธี ดังที่กล่าวไว้ในข้อความ

คุณอาจต้องการจัดเก็บรูปแบบที่เป็นมาตรฐานของฟิลด์เพื่อให้เมธอดเท่ากับสามารถทำการเปรียบเทียบที่ถูกต้องในรูปแบบมาตรฐานได้อย่างถูกต้องแทนที่จะเป็นการเปรียบเทียบที่ไม่เป็นมาตรฐานที่มีราคาแพงกว่า

Joshua Bloch หมายถึงอะไรเมื่อเขาพูดว่ารูปแบบบัญญัติ ? ฉันคิดว่าคำตอบที่กระชับของDónal เหมาะสมมาก เราสามารถจัดเก็บStringฟิลด์ต้นแบบในCaseInsensitiveStringตัวอย่างด้วยวิธีมาตรฐานบางทีอาจเป็นรูปแบบตัวพิมพ์ใหญ่ของไฟล์String. ตอนนี้คุณสามารถอ้างอิงรูปแบบมาตรฐานของCaseInsensitiveStringตัวแปรตัวพิมพ์ใหญ่และทำการประเมินราคาถูกในequalsและhashcodeวิธีการของคุณ


0

Canonical Data ใน RDBMS, Graph Data;
คิดว่าเป็น "Normalization" หรือ "Normal form" ของข้อมูลใน RDBMS ข้อมูลเดียวกันมีอยู่ในตารางที่แตกต่างกันโดยแสดงด้วยตัวระบุที่ไม่ซ้ำกันและแมปในตารางที่ต่างกัน
หรือ
คิดรูปแบบเดียวของข้อมูลในฐานข้อมูลกราฟที่แสดงในหลาย ๆ สามเท่า

ประโยชน์หลักของมันคือการทำให้ Dml (การจัดการข้อมูล) มีประสิทธิภาพมากขึ้นเนื่องจากคุณสามารถเพิ่ม (แทรก / อัปเดต) ได้เพียงค่าเดียวแทนที่จะเป็นหลายค่า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.