[英]Why is there no “List.reverse()” method in Java?
在 Java 中,要反轉 List 中的元素,我需要使用:
Collections.reverse(list)
我只是想知道為什么 Java 不在List
接口中實現 reverse 方法,以便我可以像這樣執行就地反向操作:
list.reverse()
有沒有人對此有任何想法?
為什么 Java 中沒有
List.reverse()
方法?
因為有一個Collections.reverse(List)
方法。
因為 API 設計者認為強制每個List
實現1實現一個在 99.9% 的時間都沒有使用的方法2是一個壞主意。 這可以通過使方法“可選”來解決,但這也有缺點; 例如運行時異常。
因為對於某些類型的列表(例如流包裝器/適配器),實現就地反向將是有問題的。 它通過要求將列表具體化來更改列表的內存使用特性。
另請注意, Collection
提供的reverse()
的通用實現( 源代碼)使用set
來交換元素。 它接近於標准列表類型的最佳選擇。
@shmosel 評論:
我假設 OP 是在問為什么它沒有像 List.sort() 那樣作為默認方法添加。
好點。 可能 99.9% 的論點適用。 請記住,這只會幫助那些使用 Java 8 或更高版本編譯器等構建的代碼庫的人。
1 - 這包括您的代碼庫和第 3 方庫中的實現。
2 - 86% 的統計數據用於戲劇效果:-)
因為Collection
是一個實用類,它實際上基於SOLID原則之一:
S - 單一職責原則
這個原則指出,如果我們有兩個理由改變一個類,我們必須將功能拆分為兩個類。
你有一個扮演某種角色的類,如果你需要操作內部數據,你需要創建一些子類,這將扮演另一個角色。
如果您需要list.reverse()
,則需要使用Eclipse Collections ,當您可以僅使用list.reverseThis()
,請參閱此。 在 JDK 列表中,很多方法(如 sort、max、min)沒有被添加。
這是兩種不同的 API 設計方式:
注意:這個問題是“為什么 Collections 類包含獨立(靜態)方法,而不是將它們添加到 List 接口中?”的一個非常具體的案例。 - 甚至可以認為是重復。 除此之外,爭論為每個方法的決定背后的推理是閱讀茶葉,沒有人可以告訴了針對的具體情況設計決定“的原因,” reverse
法(直到,也許喬希布洛赫帖子這里的答案) . 有趣的是, Java 集合 API 設計常見問題解答中沒有涵蓋這一點......
其他一些答案乍一看似乎令人信服,但引發了其他問題。 特別是,其中一些根本沒有給出設計決策的理由。 即使有其他方法可以模擬某個方法的行為,或者當“99.9% 的時間”都沒有使用某個方法時,將它包含在界面中仍然有意義。
查看List
接口,您會注意到您基本上可以基於另外兩個方法來實現所有方法:
T get(int index)
int size()
(對於可變列表,您還需要set
)。 這些正是AbstractList
中仍然抽象的那些。 所以所有其他方法都是相當“方便”的方法,可以基於這兩種方法規范地實現。 在這方面,我認為Sam Estep 的答案包含一個重要的觀點:人們可以爭論實施其他數十種方法。 這樣做肯定有充分的理由。 看看Collections#reverse(List)
的實際實現:
public static void reverse(List<?> list) {
int size = list.size();
if (size < REVERSE_THRESHOLD || list instanceof RandomAccess) {
for (int i=0, mid=size>>1, j=size-1; i<mid; i++, j--)
swap(list, i, j);
} else {
ListIterator fwd = list.listIterator();
ListIterator rev = list.listIterator(size);
for (int i=0, mid=list.size()>>1; i<mid; i++) {
Object tmp = fwd.next();
fwd.set(rev.previous());
rev.set(tmp);
}
}
}
那里的REVERSE_THRESHOLD
和RandomAccess
是什么東西? 說真的,如果我覺得有必要引入像RandomAccess
這樣的標記界面,我會強烈質疑我的設計。 每當你有一個像
void doSomethingWith(Type x) {
if (x instanceof Special) doSomethingSpecial((Special)x);
else doSomethingNormal(x);
}
那么這是一個強烈的跡象,表明這實際上應該是一個多態方法,應該為Special
類型相應地實現。
所以是的,將reverse
方法拉入接口中是合理的,以允許多態實現。 這同樣適用於fill
rotate
、 shuffle
、 swap
、 sort
等。 同樣,可以引入一個靜態方法,如
Collections.containsAll(containing, others);
它提供了現在使用Collection#containsAll
方法所做的事情。 但總的來說:設計師選擇了一組他們認為合適的特定方法。 Java Collections API 的核心設計者之一Joshua Bloch 在關於“如何設計一個好的 API 以及為什么它很重要”的演講中提到了忽略某些方法的原因之一:
有趣的是,在所有多態實現(通過List
接口中的方法)可能是合理的方法中,有一個實際上找到了進入接口的方法,使用 Java 8 default
方法: List#sort()
。 也許其他人,如reverse
,將在以后添加......
反向在集合中定義(帶有額外的 (s))。 這不是集合層次結構的一部分,而是作為可用於不同列表的實用程序類的一部分。
反轉列表不是定義列表的關鍵部分,因此它被排除在接口之外並單獨給出。 如果在接口中定義,每個人都必須實現它,這可能不適合所有人。
集合的創建者也可以在 List 層次結構中構建它,(由於大多數列表派生之間都有一個抽象類,他們可以將它放在中間的任何抽象類中)。 然而,為了簡化每個人的生活,將它保存在單個實用程序類中是有意義的,這樣我們就不必弄清楚要查找所有與集合相關的實用程序函數的類。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.