Составной список Java - PullRequest
       62

Составной список Java

3 голосов
/ 18 ноября 2010

Я ищу библиотеку с открытым исходным кодом, которая имеет реализацию составного списка. Мне нужен список, который читает его значения из некоторых других списков и может быть построен примерно так:

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));
Идея в том, что мне не нужно копировать все из исходных списков.

Быстрый гугл ничего не нашел, я не видел его в коллекциях Гуавы или общин (возможно, я упустил из виду) У меня действительно нет времени, чтобы реализовать это должным образом прямо сейчас.

Ответы [ 5 ]

11 голосов
/ 19 ноября 2010

Я искал внутри Гуава что-то похожее этим утром и наконец наткнулся на Iterables.concat () .

Вы специально запросили представление списка, так что это может не совсем решить вашу проблему, но об этом следует помнить.

Сначала я подумал, что мне нужна коллекция / список, но позже я понял, что не обязательно решать мою проблему: я в основном искал что-то для объединения нескольких итераций (полученных различными фильтрами / преобразованиями Гуавы) до фильтрация / преобразование результата, чтобы окончательно вывести его в ImmutableList . Возврат итерируемого представления также возможен, если вам нужно только выполнить итерацию по результату.

PS (несколько лет спустя): эти преобразования / конкатенации теперь могут выполняться с использованием потоков FluentIterable или Java 8 для Guava *.

7 голосов
/ 18 ноября 2010

CompositeCollection из Commons Collections , кажется, делает то, что вам нужно, даже если он не генерируется.

1 голос
/ 21 октября 2017

Мы можем построить один. Я использую 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());
    }
}
1 голос
/ 27 апреля 2012

Вы можете использовать org.apache.commons.collections15.collection.CompositeCollection, и это универсально.

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

0 голосов
/ 18 ноября 2010

Проверка коллекций Джавакарта, CompositeCollection:

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

...