Извлечение объектов из списка <X>на основе некоторой другой коллекции свойств списка - PullRequest
5 голосов
/ 21 апреля 2011

У меня есть класс -

public class Data implements Identifiable{
    private Integer id;

    public Integer getId(){
        return id;
    }
}

Теперь у меня есть две коллекции -

List<Data> data1 = // few hundred Objects

Set<Integer> dataIds = // few object ids

Я хотел бы извлечь List<Data> из data1, который имеет идентификаторыв dataIds

Каким должен быть мой подход?Я - гуава в своем классе, поэтому могу использовать функциональный подход гуавы, если сопоставим по производительности / эффективности.

Ответы [ 3 ]

3 голосов
/ 21 апреля 2011

Если все, что вы хотите сделать, - это выполнить итерацию по результату один раз или вам нужно многократно фильтрованное представление в режиме реального времени, вам, вероятно, нужен список без просмотра, содержащий совпадения. Создание List или Set для сохранения результата, а затем итерация по списку данных и добавление совпадений - это очень хороший подход и его легко понять!

List<Data> result = Lists.newArrayList();
for (Data data : data1) {
  if (dataIds.contains(data.getId()))
    result.add(data);
}

Я вижу, что ваш Data класс реализует интерфейс Identifiable. Учитывая это, вы можете создать Function<Identifiable, Integer>, который получает идентификатор ... Identifiables.getIdFunction() или что-то в этом роде. Это хорошо, потому что это, вероятно, было бы полезно в других местах (я говорю об этом подходе в блоге здесь ). Учитывая это, сделать это с помощью Guava также будет довольно просто:

Predicate<Identifiable> predicate = Predicates.compose(
    Predicates.in(dataIds), Identifiables.getIdFunction());
List<Data> filtered = Lists.newArrayList(Iterables.filter(data1, predicate));

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

3 голосов
/ 21 апреля 2011

Как насчет

Collections2.filter(
    data1,
    new Predicate<Data>() {
       public boolean apply(Data d) {
         return dataIds.contains(d.getId());
       }
    }
)

ps Не забывайте не слишком усложнять вещи, если только в этом нет необходимости.

0 голосов
/ 13 мая 2014

С LambdaJ вы можете написать:

List<Data> result = extract(data1, on(Data.class).getId());
...