3

我正在寻找一个具有复合列表实现的开源库。我需要一个从其他列表中读取其值的列表,并且可以像这样构造:

List list1 = new ArrayList();
list1.add("0");
List list2 = new LinkedList();
list2.add("1");
list3.add("2");
List list3 = new CompositeList(list1, list2...)
然后:
assertEquals("0", list3.get(0));
assertEquals("1", list3.get(1));
assertEquals("2", list3.get(2));
这个想法是我不需要复制源列表中的所有内容。

一个快速的谷歌没有找到任何东西,我没有在 Guava 或 commons 集合中看到它(我可能忽略了它)。我现在真的没有时间正确实施它。

4

5 回答 5

11

今天早上我在Guava里面寻找类似的东西,最后偶然发现了Iterables.concat()

您专门要求使用列表视图,因此这可能无法完全解决您的问题,但这是要牢记的一种选择。

起初我还认为我需要一个 Collection / List,但后来我意识到这不是解决我的问题的强制性:我主要是在过滤/转换之前寻找一些东西来连接多个可迭代对象(通过各种 Guava 过滤/转换获得)结果,最终将其转储到 ImmutableList中。如果您只需要迭代结果,则返回 Iterable 视图也是一种选择。

PS(几年后):这些转换/连接现在也可以使用 GuavaFluentIterable或 Java 8 流来完成。

于 2010-11-19T00:26:13.797 回答
7

Commons Collections中的CompositeCollection似乎可以满足您的需求,即使它没有被泛化。

于 2010-11-18T15:23:15.907 回答
1

您可以使用 org.apache.commons.collections15.collection.CompositeCollection,它是通用的。

请参阅http://search.maven.org/#artifactdetails%7Cnet.sourceforge.collections%7Ccollections-generic%7C4.01%7Cjar

于 2012-04-27T18:38:09.140 回答
1

我们可以建造一个。我使用 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());
    }
}
于 2017-10-21T13:47:08.657 回答
0

检查 javakarta 集合,CompositeCollection:

http://commons.apache.org/collections/apidocs/index.html

于 2010-11-18T15:38:17.557 回答