我们可以建造一个。我使用 Guava 来iterator()
实现,但自己动手并不难。
/**
* A list composed of zero to many child lists. Additions occur in the first
* acceptable list: if an insertion is attempted at an index that lies on a break
* between lists, the insert occurs in the first list. Modifications are undefined
* if list of lists has no elements.
* @param <T> Type of element stored in list.
*/
public class CompositeList<T> extends AbstractList<T> {
// member variables ---------------------------------------------------------------
private Collection<List<T>> mLists;
// constructors -------------------------------------------------------------------
public CompositeList(Collection<List<T>> pLists) {mLists = pLists;}
// methods ------------------------------------------------------------------------
/** Sum of sizes of component lists. */
public int size() {return mLists.stream().mapToInt(Collection::size).sum();}
@Override public T get(int pIdx) {
final Map.Entry<List<T>,Integer> m = findIndex(pIdx);
return m.getKey().get(m.getValue());
}
/**
* If add could occur at end of one list or beginning of the next, the former
* behavior is guaranteed.
*/
@Override public void add(int pIdx, T pElement) {
if (pIdx == 0) {
mLists.iterator().next().add(0, pElement);
} else {
// find prior object
final Map.Entry<List<T>,Integer> m = findIndex(pIdx - 1);
m.getKey().add(m.getValue() + 1, pElement);
}
}
@Override public T remove(int pIdx) {
final Map.Entry<List<T>,Integer> m = findIndex(pIdx);
// don't auto-box because remove(Object) and remove(int) can be confused
return m.getKey().remove(m.getValue().intValue());
}
@Override public T set(int pIdx, T pElement) {
final Map.Entry<List<T>,Integer> m = findIndex(pIdx);
return m.getKey().set(m.getValue(), pElement);
}
/** More efficient than superclass implementation. */
@Override public Iterator<T> iterator() {
return Iterators.concat(
Collections2.transform(mLists, Collection::iterator).iterator()
);
}
@Override public void clear() {mLists.forEach(Collection::clear);}
/**
* Identify list and index that composite index refers to. For
* [A], [], [], [B, C]; composite index 1 would return the fourth list
* mapped to the number 0.
*/
private Map.Entry<List<T>,Integer> findIndex(int pCompositeIdx) {
// composite index of list's starting point
int listStart = 0;
for (final List<T> list : mLists) {
if (listStart + list.size() > pCompositeIdx) {
return new AbstractMap.SimpleImmutableEntry<>(
list, pCompositeIdx - listStart
);
}
listStart += list.size();
}
throw new IndexOutOfBoundsException(pCompositeIdx + " >= " + size());
}
}