Как проиндексировать коллекцию с помощью составного ключа - PullRequest
2 голосов
/ 27 августа 2010

У меня есть этот класс

public class Item
{
    public int UniqueKey;
    public int Key1;
    public int Key2;
    public int Key3;
    public int Key4;
    public string Value;
}

и коллекция IEnumerable<Item>

Я хочу создать индексы для элементов этой коллекции с помощью Key1 или Key2 или составной ( Key1 и Key4 ).Количество предметов в коллекции составляет около 10 000 и более.Основная цель - производительность.У нескольких абонентов может быть много прав чтения / записи.Возвращенные коллекции должны быть защищены (защищены от внешней модификации).Может ли кто-нибудь объяснить какое-либо решение, шаблон, какие классы коллекций я должен использовать для реализации.

Я отклонил вариант использования индексов таблицы базы данных по некоторым причинам (производительность и т. Д.).

Ответы [ 3 ]

1 голос
/ 28 августа 2010

Вы можете использовать два сопоставления: одно для хранилища и одно в качестве таблицы поиска для первичного ключа.Поскольку все обновления используют первичный ключ, который должен быть исправлен, вы можете использовать снятие блокировки, чтобы разрешить одновременную запись.В этой форме писатель должен получить блокировку (primaryKey mod # locks), чтобы обновления / удаления не конкурировали за запись.И, конечно, чтение не нуждается в блокировке, если вспомогательные словари параллельны.

Вы можете увидеть Java версию этой идеи, которая была скрыта за фасадом кэширования, чтобы обеспечить хорошийAPI.

0 голосов
/ 27 августа 2010

Вы можете сгруппировать элементы, используя анонимный тип, и создать словарь с группами:

var grouped = items.GroupBy(item => new { item.Key1, item.Key4 })
                   .ToDictionary(g => g.Key, g => g.ToList());

Однако анонимные типы могут использоваться только для локальных переменных (или общих параметров метода), поэтому, если вы собираетесь хранить словарь для последующего повторного использования, вам потребуется неанонимный тип. Таким образом, вы можете создавать типы для каждой возможной комбинации клавиш или использовать класс Tuple:

Dictionary<Tuple<int, int>, Item> grouped =
              items.GroupBy(item => Tuple.Create(item.Key1, item.Key2))
                   .ToDictionary(g => g.Key, g => g.ToList());
0 голосов
/ 27 августа 2010

Вы можете использовать LINQ для возврата коллекции, проиндексированной свойством:

var key1 = from i in Items 
           group i by i.Key1 into g
           select g;

var key2 = from i in Items
           group i by i.Key2 into g
           select g;
...

Поскольку у вас небольшой, детерминированный список ключей, вы можете реализовать класс, который предоставляет группы для чтения как * 1004.* или List свойства.Добавьте один метод для добавления элементов в коллекцию (нет необходимости в отдельных методах, так как они будут сгруппированы для чтения по их значению.) Используйте ключевое слово lock в вашем методе Add для защиты коллекций элементов при добавлении.

...