Java'nın AbstractList'in removeRange () yöntemi neden korunmaktadır?


98

Herhangi bir fikri olan var mı, neden AbstractList'te (ve ayrıca ArrayList'te ) removeRange yöntemi protectednedir? Oldukça iyi tanımlanmış ve kullanışlı bir işlem gibi görünüyor, ancak yine de onu kullanmak için List uygulamasını alt sınıflara ayırmak zorundayız.

Gizli bir mantık var mı? Bana oldukça açıklanamaz görünüyor.

Yanıtlar:


163

Evet, çünkü bir aralığı dış koddan bu şekilde kaldırmazsınız. Bunun yerine şunu yapın:

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

Bu aslında removeRangeperde arkasını çağırıyor .


OP, neden genel API'nin bir removeRangeparçası olmadığını sorar List. Nedeni, Etkili Java 2. baskı Madde 40'ta açıklanmıştır ve burada alıntı yapıyorum:

Aşırı uzun parametre listelerini kısaltmak için üç teknik vardır. Birincisi, yöntemi, her biri yalnızca bir parametre alt kümesi gerektiren birden çok yönteme bölmektir. Dikkatsizce yapılırsa, bu çok fazla yönteme yol açabilir, ancak aynı zamanda ortogonaliteyi artırarak yöntem sayısını azaltmaya da yardımcı olabilir . Örneğin, java.util.Listarayüzü düşünün . Her ikisi de üç parametre gerektiren bir alt listedeki bir öğenin ilk veya son dizinini bulmaya yönelik yöntemler sağlamaz. Bunun yerine subList, iki parametre alan ve bir alt listenin bir görünümünü döndüren yöntemi sağlar . Bu yöntem , istenen işlevselliği sağlamak için her biri tek bir parametreye sahip olan indexOfveya lastIndexOfyöntemleriyle birleştirilebilir . Dahası,subListyöntem, alt listeler üzerinde rastgele hesaplamalar gerçekleştirmek için bir örnek üzerinde çalışan herhangi bir yöntemle birleştirilebilir List. Ortaya çıkan API, çok yüksek bir güç-ağırlık oranına sahiptir.

Bir iddia edebilir removeRangebirçok parametre vardır ve muhtemelen bu nedenle bir bu tedavi için aday ama çağırmak için bir yol olduğunu göz önüne alındığında gelmez removeRangearacılığıyla subList, kaplamak için hiçbir neden yoktur Listyedekli yöntemle arayüz.


AbstractList.removeRange dokümantasyon diyor ki:

Bu yöntem, clearbu listedeki işlem ve alt listeleriyle çağrılır. Liste uygulamasının dahili özelliklerinden yararlanmak için bu yöntemi geçersiz kılmak , bu listedeki ve alt Listelerindeki işlemin performansını önemli ölçüde artırabilir clear.

Ayrıca, OpenJDK'nin AbstractList.clearve SubList.removeRange.


9
Tamam, bu şekilde yapılabilir, ama neden ? Garip görünüyor. Tek tek öğeler doğrudan listeden kaldırılabilir, o zaman neden birden fazla öğe kaldırılmasın?
Joonas Pulakka

1
@Joonas: Etkili Java'nın 40. maddesi, 2. baskı bunun gerekçesini açıklıyor. Kitabın yoksa diye ilgili bölümü yapıştıracağım.
Chris Jester-Young

21
+1 (soru cevaplandı). Bununla birlikte, bir gerekçe verildiği için mantıklı olduğu anlamına gelmez. Parametre listelerini kısaltma süreci, geliştiricilerin bir API'de bulunan işlemleri anlama yeteneğini engeller, bu da doğrudan listelerin neden kısaltıldığına aykırıdır.
Sam Harwell

3
Java için çok tipik. En karmaşık ve en az etkili hale getirelim.
Tomáš Zato - Monica'yı eski durumuna getir

2
bir yan not olarak, sürüm listenin sonuna kadar uzanan bir aralıkta kullanıldığında gereksiz yere removeRangearamaların olduğunu fark ettiniz mi? hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/e2117e30fb39/src/share/... tüm arraycopy kodu tek koymak oldum böylece, 0 (yapıldığı gibi ); fark şudur: a) arraycopy, ek yüke neden olan yerel bir çağrıdır, b) arraycopy her zaman doğruluk için parametreleri kontrol eder stackoverflow.com/questions/12594046/…arraycopyArrayListnumMovedifremove
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.