Ленивый немодифицируемый список в Google Collections

Я искал достойную реализацию универсальной ленивой немодифицируемой реализации списка для обертывания моих записей результата поиска. Немодифицируемая часть задачи легка, поскольку она может быть достигнута Collections.unmodifiableList() таким образом, я только должен разобраться в ленивой части.

Удивительно, наборы Google не имеет ничего для предложения; в то время как LazyList от Apache Наборы палаты общин не поддерживает дженериков.

Я нашел попытку создать что-то сверху наборов Google, но это, кажется, неполно (например, не поддерживает size()), устаревший (не компилирует с 1,0 финалом) и требующий некоторых внешних классов, но мог использоваться в качестве хорошей начальной точки для создания моего собственного класса.

Кто-либо знает о какой-либо хорошей реализации LazyList? В противном случае то, какая опция, Вы думаете, лучше:

  • запишите мою собственную реализацию, на основе наборов Google ForwardingList, подобный тому, что сделал Peter Maas;
  • запишите мою собственную обертку вокруг Наборов палаты общин LazyList (обертка только добавила бы дженерики, таким образом, я не должен бросать везде, но только в самой обертке);
  • просто запишите что-то сверху java.util.AbstractList;

Любые другие предложения приветствуются.

Править: объяснение, почему мне нужен ленивый список.

У меня есть результат поиска Lucene (TopDocs), который является в основном набором указателей на документы Lucene. Мой класс результата поиска взял бы эти указатели в качестве входа и возвратил бы список объектов, которые сделаны из извлеченных и иначе обработанных документов Lucene. Путем обертывания всего в ленивый список я хочу удостовериться, что я не делаю дорогой обработки, когда ненужный.

8
задан Kevin Bourrillion 1 July 2010 в 01:13
поделиться

4 ответа

На самом деле я решил эту проблему другим способом. Вместо того, чтобы лениться и не изменять, я просто реализовал java.lang.Iterable . Реализация вызывает исключение UnsupportedOperationException в remove () .

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

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

4
ответ дан 5 December 2019 в 11:23
поделиться

Есть проект, который добавил функции Generics в общие коллекции Apache:

http://sourceforge.net/projects/collections/

( Коллекции Commons с Generics)

4
ответ дан 5 December 2019 в 11:23
поделиться

Решение Питера Мааса, на которое вы ссылаетесь, мне нравится - я настоятельно рекомендую вам поработать с ним, а не тратить время на его изобретение заново. Просто замените Factory на Supplier (входит в коллекцию Google).Его реализация subList также довольно умна, хотя имеет некоторые специфические последствия: если вы получите subList () и попытаетесь добавить элемент за пределы subList, вы не получите ] IndexOutOfBoundsException (как и должен делать правильный подсписок), но вы вставите в список дополнительные элементы. Скорее всего, вам не понадобятся подсписки, поэтому самым безопасным было бы реализовать этот метод, выбрасывая UnsupportedOperationException (или построив LazyList, который имеет дополнительный флаг, разрешено ли ему увеличиваться с помощью get () вызывает сверх своего размера: если он создан с помощью subList , то это не так).

size () поддерживается (автоматически самим ForwardingList ).

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

final Supplier<T> supplier = ...;
Map<Integer, T> graphs = new MapMaker()
   .makeComputingMap(
       new Function<Integer, T>() {
         public T apply(Integer index) {
           return supplier.get();
         }
       });

Поскольку List и Map более или менее представляют один и тот же абстрактный тип данных, и, поскольку из вашего комментария следует, что (1) вы не хотите, чтобы значения NULL рассматривались как элементы (хорошо!), и (2) ваша структура может быть разреженной, тогда как фактический ArrayList будет расточительным.

2
ответ дан 5 December 2019 в 11:23
поделиться

Google-коллекции и метод Guava Lists.transform дают вам лень, к которой вы стремитесь. Не хуже использовать Iterables.transform .

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

List<Supplier<ExpensiveResult>> suppliers =
    ImmutableList.copyOf(Lists.transform(keys,
        new Function<Key, Supplier<ExpensiveResult>>() {
          public Supplier<ExpensiveResult> apply(Key key) {
            return Suppliers.memoize(Suppliers.compose(
                myExpensiveFunction(),
                Suppliers.ofInstance(key)));
          }
        }));

return Lists.transform(suppliers, ThisClass.<ExpensiveResult>supplyFunction());

 . . . 

private static <T> Function<Supplier<T>, T> supplyFunction() {
  return new Function<Supplier<T>, T>() {
    public T apply(Supplier<T> supplier) {
      return supplier.get();
    }
  };
}

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

5
ответ дан 5 December 2019 в 11:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: