Фильтровать MultiMap<Предикат, значение>

Block - это несколько долгоживущих экземпляров, представляющих типы, например, A Minecraft BlockType grass, green_wool и т. Д.

Я пытаюсь найти DataStructure, которая может эффективно хранить и тестировать данный BlockPattern (например, портал обсидиана, Wither и т. Д., Если вы знакомы с Minecraft), но если вы не знакомы, то могу создать класс, который может тест для данной структуры, построенной из блоков в данном Vector3i относительно размещаемого блока.

Vector3i представляет собой целочисленный вектор "где" в "блочном шаблоне", которому может соответствовать данный предикат.

например, у вас может быть предикат, который проверяет произвольное свойство блока "hotness", которое проверяет истину для огня и лавы.

Поэтому вместо того, чтобы каждый раз сканировать весь шаблон, чтобы убедиться, что позиции блоков в мире соответствуют предикатам, я думал о том, чтобы решить проблему.

Кэшируйте потенциальные позиции, которые Блок может иметь в шаблоне в мультикарте, и получайте все потенциальные позиции, чтобы ограничить количество проверок, которые происходят впоследствии.

Итак, у меня есть Multimap<Predicate<Block>,Vector3i> PatternLookup кеш.

Который представляет потенциальные позиции, которые блоку можно найти в BlockPattern.

Таким образом, игрок размещает Блок, мне нужно отфильтровать Multimap, собирая все возможные местоположения, в которых блоку "разрешено" (предикат true) находиться.

Однако в качестве шага оптимизации я подумал, что может быть быстрее протестировать только те предикаты, которые имеют потенциальное совпадение (с точки зрения идентичности). (3 года спустя я не уверен, верно ли это предположение)

Как я могу отфильтровать содержимое мультикарты, чтобы получить коллекцию значений, используя функциональные возможности guava? (или мне лучше просто перебрать EntrySet?)

например

1 ответ

Вы могли бы использовать Multimaps.filterEntries(), что-то вроде:

public static <V> Multimap<Predicate<V>, V> filterByPredicateKey(
    Multimap<Predicate<V>, V> multimap) {
  return Multimaps.filterEntries(multimap, e -> e.getKey().apply(e.getValue()));
}

Это не совсем соответствует сигнатуре мультикарты, которую вы упоминаете в своем вопросе, но я предполагаю block а также Vector3i связаны каким-то образом, иначе вы не можете применить предикат к значениям в любом случае.

Это возвращает представление резервной мультикарты, которая свободна (O (1)) для построения, но применяет фильтрацию во время доступа, поэтому .get() на возвращенном мультикарте есть O (n). В зависимости от ожидаемых вариантов использования вы можете предпочесть скопировать эту мультикарту в отдельную неизменяемую мультикарту, чтобы фильтрация выполнялась только один раз.

Другие вопросы по тегам