2010-03-13 20 views
7

Vì vậy, trong Java, bất cứ khi nào một phạm vi được lập chỉ mục được đưa ra, giới hạn trên hầu như luôn luôn là độc quyền.Giới hạn trên của các dải được lập chỉ mục luôn được giả định là độc quyền?

Từ java.lang.String:

substring(int beginIndex, int endIndex)

Trả về một chuỗi mới đó là một chuỗi con của chuỗi này. Các chuỗi con bắt đầu vào quy định beginIndex và kéo dài đến nhân vật tại index endIndex - 1

Từ java.util.Arrays:

copyOfRange(T[] original, int from, int to)

from - chỉ số ban đầu của dãy núi này được sao chép, bao gồm
to - chỉ mục cuối cùng của phạm vi được sao chép, độc quyền.

Từ java.util.BitSet:

set(int fromIndex, int toIndex)

fromIndex - chỉ số của các bit đầu tiên được thiết lập.
toIndex - chỉ mục sau khi đặt bit cuối cùng.

Như bạn có thể thấy, có vẻ như Java cố gắng làm cho nó trở thành một quy ước nhất quán rằng giới hạn trên là độc quyền.

Câu hỏi của tôi là:

  • Đây có phải là thẩm quyền đề nghị chính thức?
  • Có những vi phạm đáng chú ý mà chúng ta nên cảnh giác không?
  • Có tên cho hệ thống này không? (Ala "0-based" vs "1-based")

Làm rõ: Tôi hoàn toàn hiểu rằng một bộ sưu tập của N đối tượng trong một hệ thống dựa trên 0 được lập chỉ mục 0..N-1. Câu hỏi của tôi là nếu phạm vi (2,4) được cung cấp, nó có thể là 3 mục hoặc 2, tùy thuộc vào hệ thống. Bạn gọi những hệ thống này là gì?

LẠI, vấn đề không phải là "chỉ số đầu tiên 0 chỉ số cuối cùng N-1" vs "chỉ số đầu tiên 1 chỉ số cuối cùng N" hệ thống; được gọi là hệ thống dựa trên 0 dựa trên 1.

Vấn đề là "Có 3 thành phần trong (2,4)" so với "Có 2 phần tử trong (2,4)" hệ thống. Bạn gọi những điều này là gì, và là một trong những chính thức bị xử phạt trên khác?

+4

Được gọi là phạm vi nửa mở. – fredoverflow

+0

Ah vâng, tôi đã nghe thuật ngữ đó trước đây. Vì vậy, bạn có thể nói rằng Bộ sưu tập Java là "0 dựa trên phạm vi nửa mở", sau đó? – polygenelubricants

Trả lời

2

Tín dụng chuyển đến FredOverflow trong nhận xét của anh cho rằng điều này được gọi là "phạm vi mở một nửa". Vì vậy, có lẽ, Bộ sưu tập Java có thể được mô tả là "0 dựa trên một nửa phạm vi mở".

tôi đã biên soạn một số cuộc thảo luận về half-open vs dãy khép kín ở nơi khác:


siliconbrain.com - 16 good reasons to use half-open ranges (sửa cho conciseness):

  • Số phần tử trong phạm vi [n, m) là chỉ m-n (và không phải là m-n+1).
  • Phạm vi trống là [n, n) (và không [n, n-1], có thể là vấn đề nếu n là một trình vòng lặp đã trỏ phần tử đầu tiên của danh sách hoặc nếu n == 0).
  • Đối với phao bạn có thể viết [13, 42) (thay vì [13, 41.999999999999]).
  • +1-1 hầu như không bao giờ được sử dụng khi xử lý phạm vi. Đây là một lợi thế nếu chúng đắt tiền (vì nó là ngày tháng).
  • Nếu bạn viết một tìm trong một phạm vi, thực tế là không tìm thấy gì có thể dễ dàng chỉ ra bằng cách trả về kết thúc làm vị trí tìm thấy: if(find([begin, end)) == end) không tìm thấy gì.
  • Trong ngôn ngữ, bắt đầu các mảng con với 0 (như C, C++, JAVA, NCL) giới hạn trên bằng với kích thước.

Half-open versus closed ranges

Ưu điểm của dãy nửa mở:

  • dãy rỗng có giá trị: [0 .. 0]
  • dễ dàng cho subranges để đi đến tận cùng của gốc: [x .. $]
  • Dễ dàng chia dãy: [0 .. x][x .. $]

Ưu điểm của dãy khép kín:

  • đối xứng.
  • Có thể dễ đọc hơn.
  • ['a' ... 'z'] không yêu cầu awkward + 1 sau 'z'.
  • [0 ... uint.max] là có thể.

Điểm cuối cùng là rất thú vị. Thật là khó xử khi viết một vị từ numberIsInRange(int n, int min, int max) với phạm vi nửa mở nếu Integer.MAX_VALUE có thể hợp pháp trong một phạm vi.

2

Chỉ cần 0 đến n-1 dựa trên.

Danh sách/Array chứa mục 0-9 được lập chỉ mục.

Bạn không thể có một danh sách dựa 0 lập chỉ mục đó là 0-n nơi cout là n, trong đó bao gồm một mục mà không tồn tại ...

Đây là cách điển hình hành mọi việc.

  1. .
  2. Phạm vi/Trang tính/Bảng tính Excel.
  3. Index (information technology)
+0

Tôi hiểu rằng một tập hợp các đối tượng 'N' trong một hệ thống dựa trên 0 được lập chỉ mục 0..N-1. Câu hỏi của tôi là nếu một phạm vi (2,4) được đưa ra, đó là 3 mục hoặc 2? – polygenelubricants

+0

+1 để có câu trả lời hay về OP – stacker

+0

Điều đó sẽ tùy thuộc vào ngữ cảnh của danh sách đối tượng mà bạn tham chiếu. Như đã đề cập trước đó, tài liệu * nên * giúp bạn với điều này. Nhiều khả năng không phải là 0, nhưng như tôi đã đề cập, có sai lệch ... –

5

Nói chung, vâng. Nếu bạn đang làm việc trong một ngôn ngữ với cú pháp C (C, C++, Java), thì các mảng không được lập chỉ mục và hầu hết các cấu trúc dữ liệu truy cập ngẫu nhiên (vectơ, danh sách mảng, v.v.) sẽ không được lập chỉ mục cũng.

Bắt đầu chỉ mục ở mức 0 có nghĩa là kích thước của cấu trúc dữ liệu luôn lớn hơn chỉ số hợp lệ cuối cùng trong cấu trúc dữ liệu. Mọi người thường muốn biết kích thước của mọi thứ, tất nhiên, và do đó thuận tiện hơn để nói về kích thước hơn là nói về chỉ mục hợp lệ cuối cùng. Mọi người quen với việc nói về việc kết thúc các chỉ mục theo kiểu độc quyền, bởi vì một mảng a[] có nghĩa là n các phần tử có phần tử hợp lệ cuối cùng trong a[n-1].

Có một lợi thế khác khi sử dụng chỉ mục độc quyền cho chỉ mục kết thúc, nghĩa là bạn có thể tính toán kích thước của danh sách con bằng cách trừ chỉ mục bắt đầu bao gồm khỏi chỉ mục kết thúc độc quyền. Nếu tôi gọi myList.sublist(3, 7) thì tôi sẽ có danh sách con với các thành phần 7 - 3 = 4 trong đó. Nếu phương pháp sublist() đã sử dụng chỉ mục bao gồm cho cả hai đầu của danh sách, thì tôi sẽ cần phải thêm một số 1 để tính toán kích thước của danh sách phụ.

Điều này đặc biệt có ích khi các chỉ số bắt đầu là một biến: Lấy sublist của myList bắt đầu từ i đó là dài 5 yếu tố chỉ myList.sublist(i, i + 5) được.

Tất cả điều đó được nói, bạn nên luôn đọc đọc tài liệu API, thay vì giả định rằng chỉ mục bắt đầu hoặc chỉ mục kết thúc nhất định sẽ được bao gồm hoặc độc quyền. Tương tự như vậy, bạn nên ghi lại mã của riêng mình để cho biết có giới hạn nào hay không.

+0

+1 cho "bạn nên luôn đọc tài liệu API" và "bạn nên ghi lại mã của riêng mình để chỉ" –

+0

Chỉ cần làm rõ mức độ liên quan đến OP, tôi tin rằng sự phổ biến của một nửa phạm vi mở trong Java đến trực tiếp từ việc sử dụng một nửa phạm vi mở trong C, mà lần lượt đến như là một phần mở rộng tự nhiên của zero-based indexing. Vì vậy, tôi nghĩ rằng một cuộc thảo luận về lập chỉ mục không dựa trên * * có liên quan đến câu hỏi ban đầu. (Điều đó đang được nói, đó là lỗi của tôi nếu tôi không tạo kết nối đó giữa các chỉ mục dựa trên zero và các phạm vi nửa mở trong câu trả lời ban đầu của tôi.) –

0

Thực tiễn này đã được giới thiệu bởi Josh Bloch vào API thu thập dưới dạng hợp đồng. Sau đó nó trở thành một tiêu chuẩn trong java và khi bất kỳ ai giết người để tạo ra một thư viện công cộng, anh ta giả định rằng anh ta nên giữ hợp đồng vì người dùng mong đợi thấy hành vi đã biết trong các thư viện mới.

+2

Vì vậy, đây là "hệ thống Bloch", sau đó? Chắc chắn điều này phải có cách sử dụng lịch sử trước khung Java/Java Collections? – polygenelubricants

+1

Tôi không biết tên của nó và tôi không chắc chắn rằng nó tồn tại. Tôi đã xem một video trên youtube nơi Josh Bloch đang nói về các nguyên tắc tốt trong thiết kế API. Và ở đó, ông nói rằng * nguyên tắc ràng buộc phía trên bao gồm ràng buộc và độc quyền thấp hơn * thực sự là một tiêu chuẩn và không nên bị vi phạm khi bạn đang phát triển các thư viện công cộng. Ông cũng đề cập đến ông là người đầu tiên (hoặc một trong những người đầu tiên, tôi không nhớ), người đã giới thiệu nó trong java. – Roman

+0

@Downvoter: bạn không đồng ý với phần nào trong câu trả lời của tôi? – Roman

0

Các chỉ mục trong mảng như cơ sở dữ liệu thực sự luôn là 0 dựa trên. String về cơ bản được hỗ trợ bởi char[]. Khung Collections nằm dưới mui xe dựa trên mảng và vân vân. Điều này làm cho việc thiết kế/duy trì/sử dụng API dễ dàng hơn mà không thay đổi cách "dưới mui xe" để truy cập (các) phần tử mong muốn trong mảng.

Tuy nhiên, có một số "ngoại lệ", chẳng hạn như phương thức setter dựa trên parameterindex của PreparedStatement và phương thức getter dựa trên columnindex là ResultSet. Họ dựa trên 1. Đằng sau hậu trường họ cũng không thực sự đại diện cho một mảng các giá trị.

Điều này có thể sẽ đưa ra một câu hỏi mới: "Tại sao chỉ mục mảng không dựa trên?". Bây giờ, nhà khoa học lập trình máy tính được kính trọng của chúng tôi E.W. Dijkstra giải thích here lý do tại sao nó nên bắt đầu bằng không.

0

Cách dễ dàng để nghĩ về phạm vi nửa mở là: cụm từ đầu tiên xác định sự khởi đầu của các phần tử trong phạm vi và cụm từ thứ hai xác định sự khởi đầu của các phần tử sau phạm vi. Hãy ghi nhớ điều đó, và tất cả sẽ giúp bạn hiểu rõ hơn. Cộng với số học hoạt động tốt hơn trong nhiều trường hợp, theo câu trả lời của @polygenelubricants.

Các vấn đề liên quan