2011-05-16 83 views
2

我有一個類A可以包含許多B類實例,它可能包含許多C類實例,它可以包含許多類的實例Djava - 關於包含在集合中的集合的實時視圖...等

現在,在AI類中有一個方法getAllD。目前每次調用都會發生很多迭代,並且會創建一個相當大的列表並返回。這不可能是非常有效的。

我想知道我該如何做得更好。這個問題Combine multiple Collections into a single logical Collection?似乎涉及到類似的話題,但我不確定如何將它應用於我的情況。

所有的評論都非常感謝!

+1

你能發表一些代碼片段嗎? – Bhushan 2011-05-16 22:50:32

+0

你真的需要所有的Ds嗎?也許你可以使用責任鏈模式通過對象層次結構分發所有Ds上的所有方法調用,而不需要收集所有的Ds。 – 2011-05-17 10:38:39

回答

0

其實我覺得Iterables.concat(或阿帕奇百科全書IteratorChain)將正常工作爲您的情況:

class A { 
    Collection<B> children; 
    Iterator<D> getAllD() { 
     Iterator<Iterator<D>> iters = new ArrayList<Iterator<D>>(); 
     for (B child : children) { 
      iters.add(child.getAllD()); 
     } 
     Iterator<D> iter = Iterables.concat(iters); 
     return iter; 
    } 
} 
class B { 
    Collection<C> children; 
    Iterator<D> getAllD() { 
     Iterator<Iterator<D>> iters = new ArrayList<Iterator<D>>(); 
     for (C child : children) { 
      iters.add(child.getAllD()); 
     } 
     Iterator<D> iter = Iterables.concat(iters); 
     return iter; 
    } 
} 
class C { 
    Collection<D> children; 
    Iterator<D> getAllD() { 
     Iterator<D> iter = children.iterator(); 
     return iter; 
    } 
} 
1

的回答你的問題是要依賴於你的情況的具體細節。這些集合是靜態的還是動態的? A在B中的收藏有多大?你只會從A訪問Ds,還是有時想在樹下或者返回Bs或Cs?你多頻繁地想要從一個特定的A訪問同一組D? D(或C或B)可以與1 A以上相關聯嗎?

如果一切都是動態的,那麼提高性能的最佳機會是將C從父對象引用到A,然後在C的D列表發生更改時更新父對象。這樣,您可以在A對象中保留一個Ds集合,並在其中一個Cs獲取新對象或刪除一個時更新A.

如果一切都是靜態的,並且每個A都有一些D集合的重用,那麼緩存可能是一個不錯的選擇,特別是如果有很多B。 A將具有一個B鍵和一個Ds集合的值的映射。 getAllDs()方法首先檢查地圖是否有B的鍵,如果是,返回它的Ds集合。如果不是,那麼它會生成集合,將其存儲到緩存映射中,然後返回集合。

您也可以使用樹來存儲對象,特別是如果它們非常簡單。例如,您可以創建一個XML DOM對象並使用XPath表達式來提取您想要的D的子集。這將允許更加動態地訪問您感興趣的對象集合。

這些解決方案在安裝成本,維護成本,結果及時性,使用靈活性和成本方面都有不同的折衷獲取結果。你應該選擇哪一個取決於你的上下文。

0

這不可能是非常有效的。

迭代內存的速度非常快。與創建具有1k個元素的10k個元素相比,創建10k個元素的效率不會有如此大的差異。因此,總而言之,您應該首先進行最直接的迭代。有可能這個工作很好。

即使您擁有gazillion元素,爲了比較而實施直接迭代也許是明智的。否則,你不知道你是否能夠進行優化,或者如果你通過巧妙做事來減慢速度。儘管如此,如果你想優化所有D的順序讀訪問,我會在外面維護一個「索引」。根據您的情況,索引可能是LinkedList,ArrayList,TreeList等。例如,如果您不確定索引的長度,避免ArrayList可能是明智之舉。如果你想使用該元素的引用有效地去除隨機元素,當你這樣做,你不用擔心你的類指數&實際參考值的一致性OrderedSet可能比列表等

好得多。即更復雜=更多地方隱藏錯誤。所以,除非你通過性能測試發現它是必要的,否則嘗試優化是不可取的。 (除非你正在談論EXTREME高性能代碼,否則避免新集合對象的實例化不會讓事情變得更快,現代JVM中的對象實例化只需要幾十納秒或者什麼東西,而且你可能會錯誤地使用ArrayList具有小的初始長度或東西,使事情變得更糟)

4

我會Iterables.transform結合Iterables.concat獲得D的實時視圖:

public class A { 
    private Collection<B> bs; 

    /** 
    * @return a live concatenated view of the Ds contained in the Cs 
    *   contained in the Bs contained in this A. 
    */ 
    public Iterable<D> getDs() { 
     Iterable<C> cs = Iterables.concat(Iterables.transform(bs, BToCsFunction.INSTANCE)); 
     Iterable<D> ds = Iterables.concat(Iterables.transform(cs, CToDsFunction.INSTANCE)); 
     return ds; 
    } 

    private enum BToCsFunction implements Function<B, Collection<C>> { 
     INSTANCE; 

     @Override 
     public Collection<C> apply(B b) { 
      return b.getCs(); 
     } 
    } 

    private enum CToDsFunction implements Function<C, Collection<D>> { 
     INSTANCE; 

     @Override 
     public Collection<D> apply(C c) { 
      return c.getDs(); 
     } 
    } 
} 


public class B { 
    private Collection<C> cs; 

    public Collection<C> getCs() { 
     return cs; 
    } 
} 

public class C { 
    private Collection<D> ds; 

    public Collection<D> getDs() { 
     return ds; 
    } 
} 

這種運作良好,如果你的目標很簡單,就是遍歷D和你並不需要一個集合查看。它避免了大型臨時集合的實例化。