2011-10-12 2 views
4

오브젝트 A 컬렉션이 있습니다. 각 A에는 B라는 개체와 관련된 필드가 있습니다. 그 중 하나는 다른 컬렉션입니다. 즉, 각 B는 As 모음집의 부속 집합에 붙습니다 (단 개념적으로는 코드가 아님). 이 필드 - A와 B의 상관 관계 -는 시스템 수명 기간 동안 변경 될 수 있습니다. 이 구조의 변경을 막는 시스템 요구 사항이 있습니다.반복 위치()와 C의 복수 콜렉션 비교 #

각 B의 A 집합에서 반복적으로 연산을 수행해야하는 경우 A 컬렉션에서 Where() 메서드를 반복하거나 B가 소유 한 다른 컬렉션을 만들고 더하기 및 관련 항목을 제거하십시오.

내가 코드에서이 캡처 할 수 있다면 어디 보자 :

class A { 
     public B owner; 
     ... 
    } 

    class B { 
     ... 
    } 

    class FrequentlyCalledAction { 
     public DoYourThing(B current) { 
     List<A> relevantItems = listOfAllAItems.Where(x => x.owner == current).ToList() 
     foreach (A item in relevantItems) { 
      ... 
     } 
     } 
    } 

대를 : 사실

class A { 
     public B owner; 
     ... 
    } 

    class B { 
     public List<A> itsItems; 
    } 

    class FrequentlyCalledAction { 
     public void DoYourThing(B current) { 
     foreach (A item in current.itsItems) { 
      ... 
     } 
     } 
    } 

    class AManager { 
     public void moveItem(A item, B from, B to) { 
     from.itsItems.remove(item); 
     to.itsItems.add(item); 
     } 
    } 
+0

얼마나 자주합니까? 얼마나 자주 A -> B 관계가 변하는가? A와 B 세트는 얼마나 큽니까? B가 A에 대한 참조를 가질 수 없습니까? – Jodrell

+0

DoYourThing은 시스템에서 가장 자주 호출되는 호출 중 하나입니다. A -> B 관계는 4 회의 DoYourThing 호출마다 한 번씩 변경됩니다. 그들은 모두 작은 세트입니다 - 아마 50 B, 아마도 100 A. – Shane

+0

A는 소유자의 소유자를 얼마나 자주 알아야합니까? 주인에게 A를 보관하고 필요할 때 주인이 누구인지 생각해 낼 수 있습니까? – Joey

답변

0

는 모든 컬렉션의 크기에 따라 달라집니다. Sol 2는 더 복잡하지만 더 큰 수집에는 더 빠르지 만 sol1은 100/1000 개 미만의 항목에 대해 매우 빠를 수 있습니다.

+0

솔루션 2의 공간 사용에 단점이 있습니까? 그것들은 모두 참으로 참고 적이기 때문에 중요합니까? 성능이 향상되면 성능이 향상됩니까? – Shane

+0

다시 말하지만 컬렉션 크기에 따라 다르지만 실제로는 목록에 저장되는 참조 일뿐입니다. – VdesmedT

1

주로 세트의 크기에 따라 다릅니다. 몇 가지 항목 만있는 경우 2 개의 솔루션과 함께 제공되는 오버 헤드가 성능 향상보다 큽니다.

이 경우 솔루션은 가독성이 뛰어나고 관리하기가 덜 복잡하므로이 경우 이라는 솔루션을 사용합니다.

세트에 수천 개의 항목이 있다면 솔루션 2 개에 갈 것입니다. moveItems 메서드는 O (n) 연산이지만 시나리오에서 쓰기보다 많은 읽기가있는 것으로 보입니다. 따라서보다 체계적인 디자인을 통해 더 많은 성과를 얻을 수 있습니다.

+0

내가 생각하는 HashSets를 사용하여 MoveItems를 O (1)로 향상시킬 수 있습니다. – Joey

0

세트가 작고 (~ 100 개) 자주 변경되므로 (~ 4 회 반복마다) 이렇게하면 문제가 있는지 확인하십시오.

public DoYourThing(B current) 
{ 
    foreach(A item in listOfAllAItems.Where(a => a.owner == current)) 
    { 
     ... 
    } 
} 

나는>은 IList의 <에 IEnumrable <을> 캐스팅에서 어떤 지점이 표시되지 않습니다.

성능상의 문제가 있다면 AManager이 최선의 답이라고 생각합니다. 관계가 얼마나 달라질 지에 따라 달라질 수 있습니다.

0

솔루션 2를 사용하는 경우 List가 아닌 HashSet을 사용하는 것이 좋습니다. Add의 경우 O (1)이고 Add의 경우 O (1)이고 remove의 경우 O (n) 인 반면 Remove는 &의 Remove입니다. 나는이 시도하지 않은

static class GlobalDictionary 
{ 
    private static Dictionary<B,HashSet<A>> dictionary = new Dictionary<B,HashSet<A>>(); 

    public static HashSet<A> this[B obj] 
    { 
    // You could remove the set and have it check to see if a Set exists for a B 
    // if not you would create it. 
    get {return dictionary[obj];} 
    set {dictionary[obj] = value;} 
    } 
} 


class A 
{ 
    private B owner; 
    public B Owner 
    { 
    get{ return owner;} 
    set 
    { 
     if (owner != null) GlobalDictionary[owner].Remove(this); 

     owner = value; 
     GlobalDictionary[owner].Add(this); 
    } 
    } 
} 

class B 
{ 
    public B() 
    { 
    GlobalDictionary[this] = new HashSet<A>(); 
    } 

    public IEnumerable<A> Children 
    { 
    get 
    { 
     return GlobalDictionary[this]; 
    } 
    } 
} 

그래서 그것이 일부 개조하면 되겠 어이 필요합니다 가능성이 높습니다 :

또 다른 옵션은 & B의 사용자가 사용하는 기억할 필요가없는 장점이있다 AManager하는이입니다 그러나 당신은 아이디어를 얻어야합니다.

+0

가비지 컬렉터가 처리 할 수 ​​있도록 전역 사전에서 B를 제거하는 방법에 대해 생각해보십시오. – Joey