我正在尝试拨打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中学习泛型。任何帮助深表感谢。 -Thanks!
答案 0 :(得分:1)
类型<E extends Comparable<E>>
很好,但还有其他一些问题:
c
是Collection
,但除非Collection
是List
,否则您无法对Collection
进行排序,因为只有List
Collection
允许按特定顺序排列和重新排列元素。其他类型的c
,例如Set
或bag,则不会。您可以将List
强制转换为c
,但仍然是排序错误的对象。看起来您想将SortedLinkedList(Collection<? extends E> c)
{
list.addAll(c);
Collections.sort(list);
}
的内容放入链接列表,然后对 进行排序:
LinkedList<Object>
列表声明为LinkedList<E>
,但应为new LinkedList();
,(or maybe List<E>
),以便声明它包含可排序对象。
list
should be new LinkedList<E>()
的分配,可以是shortened to new LinkedList<>()
。
进行足够的更改以使代码编译,但让我们深入研究。我推断你在这里尝试做的是创建一个通用的容器集合,它是一个链接列表,其中的元素始终按排序顺序保持不变。在这种情况下,您要做的一些更改是:
private
变量应为final
,以防止其他课程使用它。如果您不想在初始化后重新分配变量,那么将其设置为public
也会很好,这可以防止意外重新分配,并澄清这就是您使用它的方式。
构造函数应为compareTo
以允许从其他包进行访问。
我不确定你的LinkedList
方法是什么意思。 (如何定义一个整个集合与另一个集合的比较?)可能应将其删除。
目前您正在封装和扩展LinkedList
,这没有任何意义。您的类的每个实例都有两个 list
s,一个位于LinkedList
变量中,另一个继承自父级。你需要决定其中一个。
如果您想扩展 list
,那么您可以完全摆脱public SortedLinkedList(Collection<? extends E> c)
{
super.addAll(c);
Collections.sort(this);
}
变量并调用超类方法。 E.g:
LinkedList
在这种情况下,您需要覆盖父类的任何变量方法,以确保它们都不能用于破坏您的类按排序顺序维护其元素的不变量。例如,覆盖add(E element)
并使其在正确的位置插入新元素。虽然add(int position, E element)
应该被覆盖以抛出UnsupportedOperationException
,因为在指定的索引位置插入元素是没有意义的,因为元素在排序列表中的位置已经暗示了它的价值。
扩展LinkedList
的一个缺点是,将来可能会将新的变异方法添加到LinkedList
类,这样就可以让用户破坏你的集合的不变量。< / p>
如果您希望使用list
变量封装 extends LinkedList<E>
,那么您应删除implements List<E>
,而不是LinkedList
在这种情况下,您需要为接口的所有方法提供实现,但是您可以通过扩展Java Collections Framework提供的一个抽象骨架类来正确实现其中的大多数,例如{{3 }}
第三种可能性:既不扩展也不封装import java.lang.*;
,而是从头开始编写链表。
不需要行java.lang
。 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();
}
}
包AbstractSequentialList
中的所有内容。
以下是基于上述修复的示例:
List
大部分AbstractSequentialList
方法都可以毫不费力地实现,感谢神奇的超类ListIterator.remove()
和其超类。但是,如果您检查is imported by default,那么如果您覆盖这些方法,则可以改进,因为继承的实现主要是为了最大限度地减少扩展类的工作量。例如。要清除列表,它会迭代每个元素并小心地逐个删除它们(通过LinkedList
),而推迟到clear()
的{{1}}方法会更快。< / p>
此外,不是在添加元素后重新排序整个列表,而是将其直接插入到正确的位置会更有效。您可以通过the source执行此操作,但我会留给您:)
另一个不错的功能是允许使用自定义ListIterator.add
构建类来用于排序元素。这将允许使用未实现Comparable
的元素类型,以及覆盖默认排序的能力(例如,类的用户可以为Comparator
提供Comparator
。 case-insensitive ordering of String
s是支持此类功能的类的示例。
我希望这个例子无论如何都有助于展示概念。