Tại sao phương thức removeRange () của AbstractList của Java được bảo vệ?


98

Có ai có bất kỳ ý tưởng, tại sao phương thức removeRange trong AbstractList (và cả trong ArrayList ) protectedkhông? Nó trông giống như một hoạt động khá được xác định rõ ràng và hữu ích, nhưng vẫn để sử dụng nó, chúng tôi buộc phải phân lớp việc triển khai Danh sách.

Có một số lý do ẩn? Có vẻ khá khó giải thích với tôi.

Câu trả lời:


163

Có, vì đó không phải là cách bạn xóa một dải ô khỏi mã bên ngoài. Thay vào đó, hãy làm điều này:

list.subList(start, end).clear();

Điều này thực sự gọi removeRangelà hậu trường.


OP hỏi tại sao removeRangekhông phải là một phần của ListAPI công khai. Lý do được mô tả trong Mục 40 của Hiệu quả Java phiên bản thứ 2 và tôi trích dẫn nó ở đây:

Có ba kỹ thuật để rút ngắn danh sách tham số quá dài. Một là chia phương thức thành nhiều phương thức, mỗi phương thức chỉ yêu cầu một tập hợp con của các tham số. Nếu thực hiện bất cẩn, điều này có thể dẫn đến quá nhiều phương pháp, nhưng nó cũng có thể giúp giảm số lượng phương pháp bằng cách tăng tính trực giao. Ví dụ, hãy xem xét java.util.Listgiao diện. Nó không cung cấp các phương thức để tìm chỉ mục đầu tiên hoặc chỉ mục cuối cùng của một phần tử trong danh sách con, cả hai đều yêu cầu ba tham số. Thay vào đó, nó cung cấp subListphương thức, phương thức này nhận hai tham số và trả về một dạng xem của danh sách con. Phương thức này có thể được kết hợp với indexOfhoặc lastIndexOfcác phương thức, mỗi phương thức có một tham số duy nhất, để mang lại chức năng mong muốn. Hơn nữa,subListphương thức có thể được kết hợp với bất kỳ phương thức nào hoạt động trên một Listcá thể để thực hiện các phép tính tùy ý trên danh sách con. API kết quả có tỷ lệ công suất trên trọng lượng rất cao.

Người ta có thể tranh luận rằng removeRangekhông có nhiều tham số như vậy và do đó có lẽ không phải là ứng cử viên cho cách xử lý này, nhưng vì có một cách để gọi removeRangethông qua subList, không có lý do gì để làm lộn xộn Listgiao diện với một phương thức thừa.


Các AbstractList.removeRangetài liệu cho biết:

Phương thức này được gọi bởi clear thao tác trên danh sách này và các Danh sách con của nó. Ghi đè phương pháp này để tận dụng lợi thế bên trong của việc triển khai danh sách có thể cải thiện đáng kể hiệu suất của clearhoạt động trên danh sách này và các Danh sách con của nó.

Ngoài ra, hãy xem việc triển khai OpenJDK của AbstractList.clearSubList.removeRange.


9
Ok, nó có thể làm theo cách đó, nhưng tại sao ? Có vẻ khó xử. Các phần tử đơn lẻ có thể được xóa trực tiếp khỏi danh sách, tại sao không phải là nhiều phần tử?
Joonas Pulakka

1
@Joonas: Mục 40 của Java hiệu quả, ấn bản thứ 2 mô tả cơ sở lý luận của việc này. Tôi sẽ dán vào phần có liên quan trong trường hợp bạn không có sách.
Chris Jester-Young

21
+1 (câu hỏi đã trả lời). Tuy nhiên, chỉ vì một lý do được đưa ra không có nghĩa là nó có ý nghĩa. Quá trình rút ngắn danh sách tham số cản trở khả năng của các nhà phát triển để hiểu các hoạt động có sẵn trong một API, hoạt động trực tiếp chống lại lý do tại sao danh sách được rút ngắn ngay từ đầu.
Sam Harwell

3
Vì vậy, điển hình cho java. Hãy làm cho nó phức tạp nhất và ít hiệu quả nhất.
Tomáš Zato - Khôi phục Monica

2
như một lưu ý phụ, bạn có nhận thấy rằng removeRangecác lệnh gọi arraycopykhông cần thiết khi ArrayListphiên bản được sử dụng trên một phạm vi kéo dài cho đến cuối danh sách không? hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e2117e30fb39/src/share/… giá trị numMovedlà 0, vì vậy toàn bộ mã mảng có thể được đưa vào một if(như được thực hiện trong remove); sự khác biệt là a) arraycopy là lời kêu gọi bản địa, phát sinh trên cao, b) arraycopy không luôn luôn kiểm tra params cho đúng đắn stackoverflow.com/questions/12594046/...
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.