重复的where() vs c#中的多个集合
本文关键字:集合 where vs | 更新日期: 2023-09-27 18:10:57
我有一个对象a的集合。每个A都有一个与对象B相关的字段,我有另一个对象B的集合。换句话说,每个B都附加到a集合的一个子集(但只是在概念上,而不是在代码中)。这个将A与B相关联的场在系统的生命周期内会发生变化。有一些系统要求阻止这种结构的改变。
如果我需要对每个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) {
...
}
}
}
Vs: 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);
}
}
这主要取决于集合的大小。如果只有几个项目,那么解决方案two带来的开销大于性能增益。
在这种情况下,我将使用解决方案one,因为它具有更好的可读性,并且管理起来更简单。
如果集合中有数千个项目,我会选择解 2 。moveItems
方法是一个O(n)操作,但在您的场景中,读操作似乎比写操作多。因此,您可以通过更结构化的设计获得更高的性能。
事实上,这完全取决于您的集合的大小。sol2更复杂,但对于大的集合更快,而sol1对于少于100/1000项的集合非常快。
由于集合很小(~100个项目)并且它们经常变化(~每4次迭代),请执行此操作,然后看看是否有问题。
public DoYourThing(B current)
{
foreach(A item in listOfAllAItems.Where(a => a.owner == current))
{
...
}
}
如果这会给您带来性能问题,我认为AManager
不是您的最佳答案,尽管这可能取决于关系变化的程度。
如果您选择解决方案2,可能值得使用HashSet而不是List。对于Add & HashSet是0 (1);Remove,而List对于Add是O(1),对于Remove是O(n)。
另一个选项是这个,它的优点是A &B不需要记住使用AManager
:
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];
}
}
}
我还没有尝试过,所以它可能需要一些调整,但你应该得到的想法。