2009-11-04 2 views
196

Если у меня есть коллекция, например Collection<String> strs, как я могу получить первый элемент? Я мог просто позвонить Iterator, взять его первый next(), а затем выбросить Iterator. Есть ли менее расточительный способ сделать это?Java: Получить первый элемент из коллекции

+1

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

+0

Обобщение для любого индекса: http://stackoverflow.com/questions/1047957/best-way-to- get-value-from-collection-by-index –

+1

Похоже, вам нужна Queue.peek() – Johannes

ответ

101

Iterables.get(yourC, indexYouWant)

Потому что на самом деле, если вы используете коллекции, вы должны использовать Коллекции Google ,

+6

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

+1

Честно говоря, производительность может быть немного медленнее, чем c.iterator(). Next() - но код намного яснее и проще изменять. – Carl

+2

Я, конечно, согласен, что он чище, но ОП был расточительным, но я думаю, что, поскольку ваш ответ был принят, это то, что было желательным. – Yishai

36

Нет такой вещи, как «первый» элемент в Collection, потому что это ... ну просто коллекция.

С Collection.iterator() метода Java Дока:

Там нет никаких гарантий относительно порядка, в котором возвращаются элементы ...

Таким образом, вы не можете.

Если вы используете другой интерфейс, такой как List, вы можете сделать следующее:

String first = strs.get(0); 

Но непосредственно из коллекции это не представляется возможным.

+9

Я не думаю, что 'get (int n)' определен для 'Collection' –

+1

Вы правы, я скучаю по этому пункту. Я обновил ответ. Вы не можете! (если коллекция не реализована некоторым классом подкласса, который позволяет обеспечить гарантию) – OscarRyz

+0

get не находится в интерфейсе коллекции –

-2

Вы можете сделать это:

String strz[] = strs.toArray(String[strs.size()]); 
String theFirstOne = strz[0]; 

документация Javadoc для сбора дает следующее предостережение WRT упорядочение элементов массива:

Если эта коллекция делает никаких гарантий относительно того, что заказать его элементы возвращаются его итератором, этот метод должен возвращать элементы в том же порядке.

+2

Это создает новый массив String, намного дороже, чем создание итератора. –

+0

Да, я подумал об этом после того, как я разместил это. Независимо от используемого метода заказ зависит от базовой реализации коллекции. «Первый» затем становится относительным термином. Однако, итератор() делает это, вероятно, лучше в большинстве случаев. –

+4

-1 потому что это * никогда * лучше, чем итератор(). Next(). –

313

Похоже, что это лучший способ сделать это:

String first = strs.iterator().next(); 

Большой вопрос ... Во-первых, похоже, недосмотру для интерфейса Collection.

Обратите внимание: «first» не всегда возвращает первое, что вы положили в коллекцию, и может иметь смысл только для упорядоченных коллекций. Возможно, поэтому нет вызова get(item), так как заказ не обязательно сохраняется.

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

Например, если вы посмотрите на тип, возвращаемый методом ArrayList<String>.iterator(), мы видим, что это ArrayList::Itr. Это внутренний класс, который просто обращается к элементам списка напрямую, а не копирует их.

+9

странно, что это не принятый ответ –

+2

Важно отметить, что этот «трюк» работает только тогда, когда коллекция действительно имеет содержимое. Если он пуст, итератор может вернуть ошибку, в которой нужно предварительно проверить размер коллекции. – spaceemotion

+5

Это должен быть правильный ответ. Я не понимаю, почему ответ всегда «использует другую библиотеку!» , – Kuzeko

0

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

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

+0

Согласен, если вы не хотите итерации, не используйте коллекцию. Вместо этого используйте другой более конкретный интерфейс. –

+1

Интересно, хотя ... скажем, фактические базовые данные - это SortedSet, поэтому порядок имеет смысл, но у вас есть только представление Collection (для не глупых причин, скажем); если вы делаете сборку в список, очередь и т. д. и пытаетесь получить/poll/etc, произойдет ли катастрофа? Аналогичным образом, если базовая структура представляет собой Список, и так далее, и так далее. – Carl

+0

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

3

Похоже, ваша коллекция хочет быть список, как, так что я хотел бы предложить:

List<String> myList = new ArrayList<String>(); 
... 
String first = myList.get(0); 
45

В Java 8:

Optional<String> firstElement = collection.stream().findFirst(); 

Для более старых версий Java, есть метод GetFirst в гуавы Iterables:

Iterables.getFirst(iterable, defaultValue) 
+3

Решение java 8 особенно полезно, поскольку оно обрабатывает случай, когда коллекция пуста изящно. – SpaceTrucker

+2

Не хорошо. Вы добавляете накладные расходы на stream(), чтобы получить get (0) только потому, что вам ленится писать 4 строки кода. if (! CollectionUtils.isEmpty (productList)) { \t \t return Optional.of (productList.get (0)); } return Дополнительно.пустой(); –

+1

Отличное и простое решение. Спасибо. –

0

Это полностью зависит от того, реализация которых вы использовали, будь то ArrayList LinkedList , или другие реализации множества.

Если это реализация списка, то это просто, указав номер индекса.

2

В Java 8 у вас есть какие-то много операторов, чтобы использовать, например предел

 /** 
* Operator that limit the total number of items emitted through the pipeline 
* Shall print 
* [1] 
* @throws InterruptedException 
*/ 
@Test 
public void limitStream() throws InterruptedException { 
    List<Integer> list = Arrays.asList(1, 2, 3, 1, 4, 2, 3) 
           .stream() 
           .limit(1) 
           .collect(toList()); 
    System.out.println(list); 
} 
+0

@ Ответ Виталия Федоренко http://stackoverflow.com/a/18165855/1562662 лучше. –

2

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

Collection<String> getStrings(); 

и после вызова его, у Вас должен быть первый элемент, вы можете сделать это следующим образом:

List<String> listString = (List) getStrings(); 
String firstElement = (listString.isEmpty() ? null : listString.get(0)); 
Смежные вопросы