2015-10-16 54 views
1

我試圖打電話Collections.sort(c);但我得到一個錯誤:錯誤添加泛型集合排序方法

The method sort(List<T>) in the type Collections is not applicable 
for the arguments (Collection<capture#1-of ? extends E>) 

這裏是我的代碼:

import java.lang.*; 

public class SortedLinkedList<E extends Comparable<E>> extends LinkedList<E> { 
    LinkedList<Object> list = new LinkedList(); 
    SortedLinkedList() 
    { 

    } 

    SortedLinkedList(Collection<? extends E> c) 
    { 
     //return sorted linked list of c 
     Collections.sort(c); 
    } 

    public int compareTo(Collection<? extends E> c) { 
     // TODO Auto-generated method stub 

     return 0; 
    } 
} 

我已經聲明瞭類的通用類型擴展可比接口。 但這仍然不會幫助錯誤。我跟着這篇文章被標記爲重複的帖子,但沒有多大幫助。這是我第一次嘗試在java中學習泛型。任何幫助深表感謝。 - 謝謝!

+0

您需要的元素具有自然順序,所以它們必須是可比較的:'SortedLinkedList >擴展...' – Andreas

+0

'E'未定義爲'Collection ',['Collections.sort' ](https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#sort-java.util.List-)顯示'T'(或'E'在你的情況下)必須'Comparable','>' – MadProgrammer

+0

我改成 SortedLinkedList(集合<?延伸可比> C) \t { \t \t //返回的C有序鏈表 \t \t山口lections.sort(C); \t} \t 但錯誤仍然存​​在 – askatral

回答

1

類型<E extends Comparable<E>>是好的,但也有其他幾個問題:

  • cCollection,但除非該CollectionList你不能排序Collection,因爲只有List小號允許按特定順序排列和重新排列元素。其他類型的Collection,例如Setbag,則不。您可以輸入cList,但仍然會排除錯誤的對象。它看起來像你想放的c內容到你的鏈接列表,然後排序

    SortedLinkedList(Collection<? extends E> c) 
    { 
        list.addAll(c); 
        Collections.sort(list); 
    } 
    
  • 名單宣佈LinkedList<Object>,但應該是LinkedList<E>or maybe List<E>),所以它被聲明爲包含可排序的對象。

  • 轉讓new LinkedList();should be new LinkedList<E>(),可以是shortened to new LinkedList<>()

這是足夠的修改來編譯代碼,但讓我們深入研究。我推斷你在這裏要做的是創建一個通用容器集合,該集合是一個鏈接列表,其中的元素始終按排序順序維護。在這種情況下,你要做出一些改變是:

  • list變量應該是private,以防止其他類把玩關於它。如果你不想在初始化後重新分配變量,它也將很好,使它final,它可以防止意外重新分配,並澄清這就是你如何使用它。

  • 構造函數應該是public以允許從其他包進行訪問。

  • 我不確定您打算使用compareTo方法。 (你如何定義一個整個集合與另一個集合的比較?)可能它應該被刪除。

  • 目前,你既是封裝和擴展LinkedList,這是沒有意義的。您班級的每個實例都有兩個LinkedList s,其中一個在list變量中,一個從父級繼承。你需要決定一個或另一個。

    • 如果你想延長LinkedList那麼你就可以得到完全擺脫list變量並調用父類的方法來代替。例如: -

      public SortedLinkedList(Collection<? extends E> c) 
      { 
          super.addAll(c); 
          Collections.sort(this); 
      } 
      

      在這種情況下,你需要重寫父類的任何變化的方法,以確保沒有人可以用來顛覆您的類保持其在排序順序元素不變。例如,覆蓋add(E element)並使其將新元素插入正確的位置。而add(int position, E element)應該被覆蓋以拋出UnsupportedOperationException,因爲在指定索引位置插入元素沒有意義,因爲元素在排序列表中的位置已經被其值所隱含。

      擴展LinkedList的一個缺點是將來可能會將新的可變方法添加到LinkedList類中,這樣可以允許用戶顛覆您的集合的不變量。

    • 如果你想封裝一個LinkedListlist變量,那麼你就應該刪除extends LinkedList<E>,而是有implements List<E>

      在這種情況下,您需要爲接口的所有方法提供實現,但是您可以通過擴展Java Collections Framework提供的抽象骨架類之一(如AbstractSequentialList)來正確實現其中的大部分。

    • 第三種可能性:既不擴展也不封裝LinkedList但從頭開始編寫鏈表。

  • 該行import java.lang.*;是不必要的。一切在java.langis imported by default

以下是基於上述修正的例子:

import java.util.*; 

public class SortedLinkedList<E extends Comparable<E>> 
     extends AbstractSequentialList<E> implements List<E> { 
    private final LinkedList<E> list = new LinkedList<>(); 

    public SortedLinkedList() {} 

    public SortedLinkedList(Collection<? extends E> c) 
    { 
     list.addAll(c); 
     Collections.sort(list); 
    } 

    @Override 
    public boolean add(E element) { 
     list.add(element); 
     Collections.sort(list); 
     return true; 
    } 

    @Override 
    public ListIterator<E> listIterator(int index) { 
     // Rather than returning list.listIterator(index) directly, we 
     // encapsulate it to block the add and set methods: 
     return new ListIterator<E>() { 
      private final ListIterator<E> base = list.listIterator(index); 

      @Override 
      public boolean hasNext() { 
       return base.hasNext(); 
      } 

      @Override 
      public E next() { 
       return base.next(); 
      } 

      @Override 
      public boolean hasPrevious() { 
       return base.hasPrevious(); 
      } 

      @Override 
      public E previous() { 
       return base.previous(); 
      } 

      @Override 
      public int nextIndex() { 
       return base.nextIndex(); 
      } 

      @Override 
      public int previousIndex() { 
       return base.previousIndex(); 
      } 

      @Override 
      public void remove() { 
       base.remove(); 
      } 

      @Override 
      public void set(E e) { 
       // prevent unsorting the list 
       throw new UnsupportedOperationException(); 
      } 

      @Override 
      public void add(E e) { 
       // prevent unsorting the list 
       throw new UnsupportedOperationException(); 
      } 
     }; 
    } 

    @Override 
    public int size() { 
     return list.size(); 
    } 
} 

List方法的批量get沒有努力的感謝神奇的超AbstractSequentialList超執行。但是,如果您檢查the source,那麼如果您覆蓋這些方法,則會發現可以改進的內容,因爲繼承的實現主要是爲了最大限度地減少擴展類的工作量而設計的。例如。要清除列表,它會迭代每個元素並仔細刪除它們(通過ListIterator.remove()),而推遲到LinkedList的方法會更快。

另外,不是在添加元素後重新整理整個列表,而是直接將其插入到正確的位置,效率會更高。你可以通過ListIterator.add來做到這一點,但我會把它留給你:)

另一個不錯的功能是允許你的類與自定義Comparator構造用於排序元素。這將允許使用不執行Comparable的元素類型,以及覆蓋默認排序的能力(例如,,該班級的用戶可以爲case-insensitive ordering of Strings提供Comparator)。 TreeMap是支持這種功能的類的一個例子。

無論如何,我希望這個例子對展示概念很有幫助。

+0

非常感謝您的詳細解釋。這裏的問題是重寫的add方法沒有被調用。改爲調用Super class Linkedlists添加方法。我大聲檢查使用打印語句時,添加方法沒有返回排序列表 – askatral

+0

我不知道你的意思。你在哪裏以及如何調用'add'方法? – Boann

+0

公共類驅動程序 { \t公共靜態無效的主要(字串[] args) \t { \t鏈表列表=新鏈表(); \t \t list.add(1); list.add(3); list.add(2); } – askatral