Những ưu và nhược điểm của việc có loại CaseInsensitiveString trong Java là gì? [đóng cửa]


8

Tôi muốn tạo ra một final class CaseInsensitiveString implements CharSequence.

Điều này sẽ cho phép chúng tôi xác định các biến và trường thuộc loại này, thay vì sử dụng thông thường String. Chúng ta cũng có thể có ví dụ a Map<CaseInsensitiveString, ?>, a Set<CaseInsensitiveString>, v.v.

Một số ưu và nhược điểm của phương pháp này là gì?


Mối quan tâm tiềm năng: không gian, nhu cầu thực tập, hiệu suất, khả năng thu gom rác, v.v.
đa sinh học

Câu trả lời:


26

Không nhạy cảm trường hợp là một thuộc tính của so sánh, không phải của đối tượng (*). Bạn sẽ muốn so sánh cùng một chuỗi độc lập với trường hợp hay không tùy thuộc vào ngữ cảnh.

(Và bạn có cả một loại sâu như một trường hợp so sánh không nhạy cảm phụ thuộc vào ngôn ngữ - tôi được đặt ở trên là tiếng Thổ Nhĩ Kỳ - và thậm chí cả bối cảnh - tùy thuộc vào từ và phương ngữ ß có thể được đặt lên trên như SS hoặc SZ bằng tiếng Đức.)

(*) Nó có thể là một thuộc tính của đối tượng chứa chuỗi, nhưng điều đó hơi khác với việc là một thuộc tính của chính chuỗi đó. Và bạn có thể có một lớp không có trạng thái ngoại trừ một chuỗi và so sánh hai trường hợp của lớp đó sẽ sử dụng một trường hợp so sánh không nhạy cảm của chuỗi. Nhưng lớp đó sẽ không phải là một chuỗi mục đích chung vì nó sẽ không cung cấp các phương thức được mong đợi cho một chuỗi mục đích chung và sẽ cung cấp các phương thức không có. Lớp này sẽ không được gọi là CaseInsensitiveString nhưng PascalIdentifier hoặc bất cứ điều gì thích hợp để mô tả nó. Và BTW, thuật toán so sánh độc lập trường hợp có thể sẽ được cung cấp bởi mục đích của nó và độc lập với miền địa phương.


1
Vì vậy, bạn sẽ đề nghị TreeSet<String>sử dụng String.CASE_INSENSITIVE_ORDERhơn một HashSet<CaseInsensitiveString>? Lưu ý rằng sử dụng TreeSetphương tiện O(log n)cho contains. Hơn nữa, so sánh này là không phù hợp với equals, có nghĩa là kết quả TreeSetkhông tuân thủ chung Sethợp đồng (tức là nó có thể contains(x), mặc dù nó không có yếu tố đó là equalsđến x).
đa gen

Từ giữa năm 90, các bảng băm chung mà tôi đã thiết kế có cả hàm băm và hàm đẳng thức làm tham số chung với mặc định được suy ra từ loại khóa. (Nếu không phải là trường hợp được cung cấp bởi thư viện Java, tôi sẽ mạo hiểm giải thích rằng chúng được thiết kế bởi một người quen thuộc với lập trình OO hơn là lập trình chung, gõ mạnh loại đó với các thao tác đó là việc bạn cần làm trong OOP nhưng một mùi mã trong GP).
AProgrammer

@AProgrammer Các bộ sưu tập Java sử dụng việc equals()triển khai trên từng đối tượng. Có một triển khai mặc định, mà bất kỳ đối tượng nào cũng có thể ghi đè. Tôi không nghĩ bạn có thể định nghĩa hàm băm, nhưng sau đó tôi chưa bao giờ thử - các bảng luôn hoạt động tốt mà không phải lo lắng về nó (một lý do tôi thích Java hơn C ++ :)).
Michael K

1
@AProgrammer - Tôi không đồng ý với "Không nhạy cảm trường hợp là một thuộc tính của so sánh, không phải của đối tượng" và với "có thể là đối tượng nhưng không phải là chuỗi" proviso. Điều này có thể mô tả mọi thứ như thế nào, nhưng câu hỏi là về một sự thay đổi được đề xuất đối với cách mọi thứ đang diễn ra. Trong số học modulo 3, 2 là tốc ký cho {..., -4, -1, 2, 5, 8, 11, ...}. Ký hiệu đại diện cho một sự trừu tượng, nhưng không giống với sự trừu tượng. Tại sao 'H' không thể biểu thị sự trừu tượng {'h', 'H'}? Các ký tự hoàn toàn không tồn tại trong bộ nhớ máy tính - cho dù mã đại diện cho 'H' hay {'h', 'H'}, đó là một sự trừu tượng.
Steve314

1
@AProgrammer - trên đoạn thứ hai, tôi có thể đồng ý mặc dù. Ít nhất, nó sẽ bao hàm các chuỗi không phân biệt chữ hoa chữ thường, các chuỗi không phân biệt chữ hoa chữ thường, v.v. Một lớp có các lớp con hoặc tùy chọn i18n, IOW. Và sau đó bạn nhận được vấn đề công văn kép (làm thế nào để so sánh hai chuỗi không phân biệt chữ hoa chữ thường với các tùy chọn ngôn ngữ khác nhau). Tôi đoán đó là trở lại "tài sản của so sánh". Chỉ trích!
Steve314

7

Chỉ cần ra khỏi đầu của tôi:

Ưu điểm:

  • Làm cho rất nhiều mã tự viết tài liệu, ví dụ:
    • bool UserIsRegistered(CaseInsensitiveString Username)
  • Có thể so sánh hợp lý
  • Có thể loại bỏ khả năng lỗi so sánh

Nhược điểm:

  • Có thể lãng phí thời gian
    • mọi người chỉ có thể chuyển đổi các chuỗi thông thường thành chữ thường nếu họ cần so sánh không phân biệt chữ hoa chữ thường
  • Sử dụng nó cho mã front-end sẽ gây ra vấn đề viết hoa
    • Ví dụ: nếu bạn sử dụng CaseInsensitiveStringđể lưu trữ tên người dùng, mặc dù có ý nghĩa so sánh back-end không phân biệt chữ hoa chữ thường, mã mặt trước sẽ hiển thị tên người dùng là "bob smith" hoặc "BOB SMITH"
  • Nếu cơ sở mã của bạn đã sử dụng các chuỗi thông thường, bạn sẽ phải quay lại và thay đổi chúng hoặc sống với sự không nhất quán

4
Tùy thuộc vào việc triển khai, điểm "Nhược điểm" thứ hai của bạn không phải là hợp lệ - bạn có thể triển khai CaseInsensitiveString để lưu trữ phân biệt chữ hoa chữ thường và chỉ ghi đè các toán tử so sánh.
tdammers

1
@tdammers: nếu CaseInsensitiveString được lưu trữ với case và sau đó với toán tử so sánh được ghi đè, nó củng cố quan điểm của @AProgrammer rằng toán tử so sánh có thể được tách rời khỏi đối tượng chuỗi bất kỳ.
rwong

3
@tdammers - một số thứ đã hoạt động tương tự. Hệ thống tập tin Windows bảo vệ trường hợp, ví dụ, nhưng không nhạy cảm trường hợp để so sánh. Đây không phải là một hệ thống tồi, nhưng có thể gây nhầm lẫn khi bạn muốn "đổi tên" thứ gì đó để thay đổi trường hợp. Về cơ bản, đôi khi bạn vẫn cần so sánh phân biệt chữ hoa chữ thường để tránh đưa ra những đánh giá tồi tệ về việc liệu một người đổi tên có thực hiện thay đổi thực sự hay không - và nếu có một trường hợp đặc biệt, có thể cũng có những trường hợp khác.
Steve314

@rwong: Tôi đồng ý. Điều tốt nhất sẽ là so sánh trường hợp không nhạy cảm rõ ràng khi cần thiết. Tuy nhiên, đôi khi bạn muốn các chuỗi hoạt động giống như các chuỗi SQL (với đối chiếu CI), sau đó bảo toàn trường hợp lưu trữ nhưng bỏ qua trường hợp so sánh sẽ là kết hợp gần nhất.
tdammers

4

CaseInsensitiveString không phải là một ý tưởng tồi phụ thuộc vào việc sử dụng của bạn, miễn là bạn không mong đợi nó hoạt động cùng với String.

Bạn có thể chuyển đổi CaseInsensitiveString thành Chuỗi hoặc ngược lại và đó là tất cả những gì bạn nên làm.

Vấn đề sẽ xảy ra nếu bạn cố gắng làm một cái gì đó như

class CaseInsensitiveString {
  private String value;

  public boolean equals(Object o) {
    // .....
    if (o instanceof String) {
      return value.equalsIgnoreCase((String) o);
    }
  }
}

Bạn chắc chắn sẽ thất bại nếu bạn định biến CaseInsensitiveString của mình thành Chuỗi bình thường, bởi vì bạn sẽ vi phạm tính đối xứng và tính bắc cầu cho bằng () (và các hợp đồng khác)

Tuy nhiên, vui lòng tự hỏi, trong trường hợp nào bạn thực sự cần CaseInsensitiveString mà nó không phù hợp để sử dụng String.CASE_INSENSITIVE_ORDER? Tôi đặt cược không nhiều trường hợp. Tôi chắc chắn sẽ có trường hợp đáng để có lớp học đặc biệt này, nhưng hãy tự hỏi mình trước.


2

Rõ ràng việc tạo các loại trong miền / mô hình của bạn là thực hành rất tốt. Giống như Maxpm nói nó là tài liệu tự. Cũng là một điểm cộng lớn: mọi người không thể (vô tình) sử dụng đầu vào sai. Điều tiêu cực duy nhất nó có là nó sẽ khiến các lập trình viên cơ sở (và thậm chí một số người trung gian) sợ hãi.


1

Một lớp CaseInsensitiveString và các trình trợ giúp của nó thêm rất nhiều mã và chúng sẽ làm cho mọi thứ dễ đọc hơn phương thức String.toLoweCase ().

CaseInsensitiveString vaName1 = new CaseInsensitiveString('HeLLo');
//... a lot of lines here
CaseInsensitiveString vaName2 = new CaseInsensitiveString('Hello');
//... a lot of lines here
if (varName1.equals(varName2)) ...

phức tạp hơn, ít tài liệu hơn và kém linh hoạt hơn

String vaName1 = 'HeLLo';
//... a lot of lines here
String vaName2 = 'Hello';
//... a lot of lines here
if (varName1.toLowerCase().equals(varName2.toLowerCase())) ...

0

Các triển khai được sử dụng thường xuyên nhất trên web là phân biệt chữ hoa chữ thường - XML, JavaScript. Về mặt hiệu suất, tốt nhất là luôn sử dụng hàm / thuộc tính / đối tượng phù hợp nhất cho từng trường hợp.

Nếu bạn đang xử lý các cấu trúc - XML ​​hoặc JS hoặc tương tự, độ nhạy trường hợp là quan trọng. Nó là nhanh hơn nhiều bằng cách sử dụng các thư viện hệ thống.

Nếu bạn đang xử lý dữ liệu trong cơ sở dữ liệu, như đã đề cập ở trên, việc lập chỉ mục cơ sở dữ liệu sẽ được sử dụng cho các chuỗi phân biệt / phân biệt chữ hoa chữ thường.

Nếu bạn đang xử lý dữ liệu một cách nhanh chóng, điều quan trọng là phải thực hiện tính toán chi phí chuyển đổi cần thiết cho mỗi chuỗi. Có thể là các chuỗi nên được so sánh hoặc sắp xếp bằng cách nào đó.

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.