我的任务是解决以下问题:创建一个将实现 List 的集合 ReverseList。通过使用 for 循环 (for(E e:list)) 迭代 ReverseList 类型的对象列表,我们将按照与输入顺序相反的顺序获取项目。 在从 ArrayList 扩展的同时实现以下类
所以本质上我需要创建一个不遵循插入自然顺序的集合 让我澄清一下,我不希望在创建列表后反转列表并使用 Collections.reverse() 之类的内容添加项目,而是让列表保持自己的顺序
到目前为止我尝试过的是制作一个自定义迭代器。但是由于某种原因,当尝试迭代列表时,我被 IndexOutOfBoundsException 抛出(即使列表不为空) 我的代码:
public class ReverseList<E> extends ArrayList<E> implements List<E>{
private class ReverseIterator<E> extends ReverseList<E> implements Iterator<E>
{
private int pos;
public ReverseIterator()
{
pos = super.size()-1;
}
public ReverseIterator(ReverseList<E> r)
{
pos = r.size()-1;
}
@Override
public boolean hasNext() {
return pos >= 0;
}
@Override
public E next() {
return super.get(pos--);
}
}
@Override
public Iterator<E> iterator() {
// TODO Auto-generated method stub
return new ReverseIterator<E>(this);
}
public static void main(String[] args)
{
ReverseList<Integer> r = new ReverseList<>();
r.add(new Integer(1));
r.add(new Integer(2));
r.add(new Integer(3));
r.add(new Integer(4));
for(Integer i:r)
{
System.out.println(i);
}
}
}
抛出错误:线程“main”中的异常 java.lang.IndexOutOfBoundsException:索引 3 超出长度 0 的范围(在 for 循环中抛出)
为什么列表长度为0?
我的方法可行吗?有更好的方法吗?
您的
ReverseIterator
是 ReverseList
的子类。这意味着,它本身就是一个列表。然后,您混淆了这两个列表的状态。在 ReverseIterator(ReverseList<E> r)
中,您使用 r
的大小来初始化 pos
,在 next()
中,您使用 super.get(pos--)
来访问其他列表的内容。其他列表始终为空。
迭代器永远不应该是集合。当您将迭代器实现为内部类时,您可以隐式访问外部集合的状态。
除此之外,您的列表显然违反了
List
接口的约定,并且将来会导致很多其他问题,因为它的 iterator()
与其他 List
功能不一致,例如所有基于索引的操作或 listIterator()
.
您不应该仅仅为了单个操作(即向后迭代)而改变类的基本原理。相反,将此单个操作实现为不同的操作。
例如:
public class ReversibleList<T> extends ArrayList<T> {
private class ReverseIterator implements Iterator<T> {
private int pos = size() - 1;
@Override
public boolean hasNext() {
return pos >= 0;
}
@Override
public T next() {
return get(pos--);
}
}
public Iterable<T> reverse() {
return () -> new ReverseIterator();
}
public static void main(String[] args) {
ReversibleList<Integer> r = new ReversibleList<>();
r.add(1);
r.add(2);
r.add(3);
r.add(4);
for(Integer i: r.reverse()) {
System.out.println(i);
}
}
}
reverse()
视图没有自己的存储空间,但始终以相反的顺序反映列表的当前内容。原来的List
继续履行着契约。
请注意,可以创建列表的反向视图,以支持
List
界面超出 iterator()
的其他操作:
public class ReversibleList<T> extends ArrayList<T> {
private class ReversedList extends AbstractList<T> implements RandomAccess {
@Override
public T get(int index) {
return ReversibleList.this.get(size() - index - 1);
}
@Override
public int size() {
return ReversibleList.this.size();
}
}
public List<T> reverse() {
return new ReversedList();
}
public static void main(String[] args) {
ReversibleList<Integer> r = new ReversibleList<>();
r.add(1);
r.add(2);
r.add(3);
r.add(4);
r.reverse().subList(1, 4).stream().forEach(System.out::println);
}
}
创建一个不遵循插入自然顺序的集合
这是一个矛盾的说法。自然顺序不是插入顺序。
compareTo
接口所需的 Comparable
方法的类实现进行排序。List#reversed
我不打算在创建后反转列表
所以按照正常方向构建列表。之后,在 Java 21+ 中,只需调用
List#reversed
即可获取该列表上的视图,该视图显示与默认遭遇顺序相反的遭遇顺序。
List < Integer > integers = new ArrayList <>( 3 );
integers.add( 42 );
integers.add( 99 );
integers.add( 7 );
System.out.println( "integers = " + integers );
Collections.sort( integers ); // Sort in natural order.
List < Integer > reversedIntegers = integers.reversed( ); // Present encounter order that is opposite of the previously set natural order.
System.out.println( "integers = " + integers );
System.out.println( "reversedIntegers = " + reversedIntegers );
运行时:
integers = [42, 99, 7]
integers = [7, 42, 99]
reversedIntegers = [99, 42, 7]
要了解更多信息,请参阅 JEP 431:排序集合。