根据 cmets,目标是在串联列表上创建类似于“视图”的东西 - 意味着数据不应该被复制。相反,给定的列表应该像单个列表一样“出现”。
实现这一点的一种方法是扩展AbstractList。 get(int) 和 size() 的实现相当简单。关键是为串联列表创建一个Iterator。以下是一个非常简单的草图,说明了如何实现这一点(但请参阅下面的注释)
import java.util.AbstractList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class MergedListTest
{
public static void main(String[] args)
{
testBasic();
testEmptyA();
testEmptyB();
}
private static void testBasic()
{
List<Integer> list0 = Arrays.asList(0,1,2);
List<Integer> list1 = Arrays.asList(3,4,5);
List<Integer> expected = Arrays.asList(0,1,2,3,4,5);
List<Integer> actual = new MergedList<Integer>(list0, list1);
System.out.println(actual.equals(expected));
}
private static void testEmptyA()
{
List<Integer> list0 = Collections.emptyList();
List<Integer> list1 = Arrays.asList(3,4,5);
List<Integer> expected = Arrays.asList(3,4,5);
List<Integer> actual = new MergedList<Integer>(list0, list1);
System.out.println(actual.equals(expected));
}
private static void testEmptyB()
{
List<Integer> list0 = Arrays.asList(0,1,2);
List<Integer> list1 = Collections.emptyList();
List<Integer> expected = Arrays.asList(0,1,2);
List<Integer> actual = new MergedList<Integer>(list0, list1);
System.out.println(actual.equals(expected));
}
}
class MergedList<T> extends AbstractList<T>
{
private final List<T> list0;
private final List<T> list1;
MergedList(List<T> list0, List<T> list1)
{
this.list0 = list0;
this.list1 = list1;
}
@Override
public T get(int index)
{
if (index < list0.size())
{
return list0.get(index);
}
return list1.get(index - list0.size());
}
@Override
public Iterator<T> iterator()
{
return new Iterator<T>()
{
private Iterator<T> current = list0.iterator();
private boolean first = true;
@Override
public boolean hasNext()
{
return current != null && current.hasNext();
}
@Override
public T next()
{
T result = current.next();
if (!current.hasNext())
{
if (first)
{
current = list1.iterator();
}
else
{
current = null;
}
}
return result;
}
};
}
@Override
public int size()
{
return list0.size() + list1.size();
}
}
从概念上讲,从AbstractSequentialList 继承会更有意义:AbstractList 提供存根实现,例如iterator(),最终委托给 get(int),而 AbstractSequentialList 提供“相反的”存根实现,例如get(int) 最终委托给 iterator()。但是,这需要一个ListIterator<T> 实现,这比上面的简单草图要复杂一些。
另外请注意,我假设生成的视图应该是不可修改的 - 但这应该与给定的描述一致。
最后,请注意(当然)已经有针对此任务和类似任务的实现,并且这些实现可能远比上面概述的更复杂。例如,Google Guava 提供了不同的 Iterators#concat 方法,允许您连接多个迭代器。所以如果你已经在使用 Guava,上面的iterator() 方法的实现可以归结为
@Override
public Iterator<T> iterator()
{
return Iterators.concat(list0.iterator(), list1.iterator());
}