2013-08-23 1 views
2

Предусматривает ли какая-либо общая библиотека Java метода для найти элемент в конечной коллекцииигарантировать, что именно один матч?метод библиотеки Java, чтобы найти элемент в коллекции и проверить, есть ли в точности один матч

Метод мог бы, например, вернуть null, если ничего не было найдено и выбрано исключение, если было найдено несколько элементов.

В настоящее время я использую свою собственную реализацию (см. Ниже), но я бы не стал загрязнять бизнес-код такими полезными методами (даже если они были извлечены в отдельный пакет утилиты).

Я также не хочу, чтобы накладные расходы на повторное использование более одного раза или накладные расходы на сборку фильтров и просмотр длины результата.

P.S. мое текущее решение (которое работает, но должен быть заменен методом библиотеки):

public static <T> T getSingleMatch(Iterable<T> lookIn, com.google.common.base.Predicate<? super T> predicate) { 
    T foundItem = null; 
    for (T item : lookIn) { 
     if (predicate.apply(item)) { 
      if (foundItem != null) 
       throw new RuntimeException("multiple matches"); // alternatively: `return null;` 
      else 
       foundItem = item; 
     } 
    } 
    // alternatively: `if (foundItem == null) throw ...` 
    return foundItem; 
} 
+0

Почему вы это требование? Без дополнительной информации, похоже, что вам лучше использовать «Set» в первую очередь. Поведение изменилось бы на исключение при вставке (конечно, вам нужно проверить возвращаемое значение 'add'). Или вы можете использовать MultiSet. Или это требование работать на всех видах Итераций? – Axel

+0

@Axel: Спасибо за ваше предложение. Я получаю «Итерируемый» из внешнего интерфейса; он может содержать несколько элементов, которые соответствуют некоторым критериям (сложные - не просто '.equals()'), а бизнес-логике (==> 'RuntimeException') не допускается. Библиотека 3rdparty фактически возвращает 'ArrayList' * в своей текущей реализации *, но я не хочу полагаться на это. Количество элементов может быть очень большим, и все, что мне нужно, это извлечь один элемент - вот почему я не хочу накладных расходов на создание 'Set' именно для этой цели. –

ответ

3

Один из вариантов, чтобы выделить две идеи на два метода, так что каждый метод делает одну вещь - а затем объединить вызовы

  • Один из способов лениво фильтр, возвращая последовательность соответствующих результатов
  • Один метод возвращает элемент из последовательности, требуя от него быть единственным элементом

Guava имеет как те:

Так, например:

String match = Iterables.getOnlyElement(Iterables.filter(source, predicate)); 
+0

Мне не было известно о 'Iterables.getOnlyElement', это именно то, что мне нужно. Мне нужно как-то найти время, чтобы лучше посмотреть на Гуаву ... –

+0

@AlexShesterov: Да, Гува прекрасна :) –

2
int index = collection.indexOf(item); 
if (index != -1 && index == collection.lastIndexOf(item)) { 
    // one and only one 
} 

Если index != -1 это не означает, что нет такого пункта. Если следующий оператор if не оценивает значение true, это означает, что существует как минимум 2 элемента. Вы можете реструктурировать его для исключения исключений, возврата null или возврата индекса или элемента. Надеюсь, вы знаете, как это сделать на основе вашего вопроса.

+0

спасибо за ваш ответ; хотя это не сработает для 'Iterables', , это, безусловно, очень приятное решение для' Collection'; +1. –

+0

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

+0

Эй, если вы решите использовать коллекцию в любом случае, есть частота (Collection c, Object o) – Xabster

 Смежные вопросы

  • Нет связанных вопросов^_^