Ответ 1
Вы можете использовать Iterator
как для получения единственного элемента, так и для проверки того, что коллекция содержит только один элемент (тем самым избегая вызова size()
и создания ненужного списка):
Iterator<Element> iterator = set.iterator();
if (!iterator.hasNext()) {
throw new RuntimeException("Collection is empty");
}
Element element = iterator.next();
if (iterator.hasNext()) {
throw new RuntimeException("Collection contains more than one item");
}
return element;
Обычно вы завершаете это по своему собственному методу:
public static <E> E getOnlyElement(Iterable<E> iterable) {
Iterator<E> iterator = iterable.iterator();
// The code I mentioned above...
}
Обратите внимание, что эта реализация уже является частью библиотек Guava (которую я очень рекомендую, даже если вы не используете ее для этого конкретного код). Более конкретно, метод относится к классу Iterables
:
Element element = Iterables.getOnlyElement(set);
Если вам интересно, как это реализовано, вы можете посмотреть Iterators
исходный код класса (методы в Iterables
часто вызывают методы в Iterators
):
/**
* Returns the single element contained in {@code iterator}.
*
* @throws NoSuchElementException if the iterator is empty
* @throws IllegalArgumentException if the iterator contains multiple
* elements. The state of the iterator is unspecified.
*/
public static <T> T getOnlyElement(Iterator<T> iterator) {
T first = iterator.next();
if (!iterator.hasNext()) {
return first;
}
StringBuilder sb = new StringBuilder();
sb.append("expected one element but was: <" + first);
for (int i = 0; i < 4 && iterator.hasNext(); i++) {
sb.append(", " + iterator.next());
}
if (iterator.hasNext()) {
sb.append(", ...");
}
sb.append('>');
throw new IllegalArgumentException(sb.toString());
}