2010-11-18 68 views
3

我正在尋找一個具有複合列表實現的開源庫。 我需要一個從其他列表中讀取其值的列表,並且可以像這樣構建:Java複合列表

List list1 = new ArrayList(); 
list1.add("0"); 
List list2 = new LinkedList(); 
list2.add("1"); 
list3.add("2"); 
List list3 = new CompositeList(list1, list2...) 
then:
assertEquals("0", list3.get(0)); 
assertEquals("1", list3.get(1)); 
assertEquals("2", list3.get(2)); 
這個想法是我不需要複製源列表中的所有內容。

快速谷歌沒有找到任何東西,我沒有看到它在番石榴或公共收藏(我可能忽略了它)。 我現在沒有時間正確實施它。

+0

那麼你在尋找一個實時視圖嗎?如果你回去向list1添加內容,你期望什麼行爲? – 2010-11-18 15:23:35

+0

@標記是的,它必須是活的。 – AmanicA 2010-11-18 15:26:59

+0

可以解釋爲什麼你會想要這個?你最好創建一個包含所有期望元素的新列表(請不要說這是出於性能原因:P) – 2010-11-18 15:27:46

回答

7

CompositeCollectionCommons Collections似乎做你所需要的,即使它沒有generified。

+0

我實際上有些害怕,任何圖書館都有這個。它會重新排列任何時候任何基礎集合發生更改時返回的元素。當然,除非它複製它們,OP明確不想要的。 – Powerlord 2010-11-18 15:26:18

+5

@ R. Bemrose:有各種各樣的裝飾器類類的實例,要求你只用*從那時起使用裝飾器來正常工作。如果你從'Collections'獲得'unmodifiableList',你仍然可以返回並更改你傳入的列表,從而也改變了不可修改的列表。如果OP不遵循使用條件,則不能進行擔保。現在,這絕對應該*記錄在Javadoc ... – 2010-11-18 15:27:50

+0

如果它是一個聚合列表,它本來會很好。 – AmanicA 2010-11-18 21:27:06

11

今天上午我看裏面番石榴類似的東西,最後偶然發現Iterables.concat()

您特別要求列表視圖,所以這可能不會完全解決您的問題,但這是一個選項要記住。我之前也認爲我需要一個Collection/List,但後來我意識到解決我的問題並不是強制性的:我主要是想找出一些東西來連接多個迭代(通過各種Guava過濾/轉換獲得),在過濾/轉換結果之前,最後到dump it into an ImmutableList。如果您只需要迭代結果,則返回Iterable視圖也是一個選項。 PS(幾年後):現在可以使用Guava的FluentIterable或Java 8流完成這些轉換/連接。

1

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

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

+0

由於包名稱使它看起來像Apache項目,鏈接或引用本來就不錯。 – madth3 2012-10-26 22:44:33

+0

它在這裏:http://search.maven.org/#artifactdetails%7Cnet.sourceforge.collections%7Ccollections-generic%7C4.01%7Cjar – rodche 2013-10-01 03:49:12

0

我們可以構建一個。我使用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()); 
    } 
}