Java: получить первый элемент из коллекции

Asked
Viewd367184

285

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

  • Конечно, может быть лучший способ получить доступ к первому элементу, если вы знаете реализующий класс контейнера…

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

    Ciro Santilli 郝海东冠状病六四事件法轮功23 марта 2015, 16:37
  • Похоже, вам нужен Queue.peek ()

    Johannes28 октября 2015, 10:21

12 ответов

131

Iterables.get (yourC, indexYouWant)

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

  • Иногда вы просто используете код, который использует коллекции, так что делать нечего.

    erickrf09 августа 2015, 03:08
  • Я, конечно, согласен, что он чище, но OP был расточительным, но я полагаю, что, поскольку ваш ответ был принят, это именно то, что нужно.

    Yishai05 ноября 2009, 20:03
  • Честно говоря, с точки зрения производительности он может быть немного медленнее, чем c.iterator (). next (), но код намного понятнее и проще изменять.

    Carl04 ноября 2009, 04:14
  • Он делает то же самое, просто сначала проверяет, является ли это списком, и получает по индексу, если это так.В нем также есть некоторый код, чтобы попытаться быстрее выйти из строя в реальной коллекции (то есть, если индекс слишком велик, он пытается выяснить это, не повторяя все это и не выбрасывая исключение в конце).

    Yishai04 ноября 2009, 03:37
  • Из комментариев команды:

    Возвращает первый элемент в iterable или defaultValue, если итерируемый объект пуст.Аналог этого метода Iterators - Iterators.getNext (java.util.Iterator Extends T>, T). Если значение по умолчанию не требуется (и вызывающий абонент вместо этого хочет, чтобы было выброшено исключение NoSuchElementException), рекомендуется вместо этого использовать iterable.iterator (). Next (). Итак, значение по умолчанию не требуется, тогда используйте iterable.iterator (). Next ()!

    oikonomopo11 декабря 2014, 14:33
  • Для тех (все еще) прибывающих сюда: я думаю, что ответ jheddings, вероятно, лучший ответ «сделай это», хотя я бы предпочел @DonaldRaab (внизу страницы) для случаев, когда я уже использую GC.библиотека.Мой ответ действительно для случая, когда кто-то может захотеть написать гибкость на будущее (скажем, если кто-то решит, что элемент второй - это новая горячность).

    Carl24 мая 2013, 10:24
4

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

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

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

 Collection<String> stringCollection = ...;
String string = collection.stream().collect(MoreCollectors.onlyElement())
 

Если вы не уверены в количестве элементов, используйте findFirst.

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

Это полностью зависит от того, какую реализацию вы использовали, будь то связанный список arrayylist или другие реализации набора.

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

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

88

В java 8:

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

Для более старых версий java в Guava есть метод getFirst Iterables :

 Iterables.getFirst(iterable, defaultValue)
 
  • Решение java 8 особенно полезно, поскольку оно корректно обрабатывает случай, когда коллекция пуста.

    SpaceTrucker16 февраля 2016, 08:14
  • У меня нет доступного метода getFirst.Есть методы get и getLast

    user120921603 августа 2017, 05:41
  • @ R.S, а что произойдет, если вы не можете вызвать productList.get (0), поскольку это коллекция…?(Согласно вопросу OP)

    Denham Coote16 ноября 2017, 14:17
  • Плохо.Вы добавляете накладные расходы на stream (), чтобы получить get (0) только потому, что вам лень написать 4 строки кода.

     if(!CollectionUtils.isEmpty(productList)){
      return Optional.of(productList.get(0));
    }
    return Optional.empty();
     
    R.S22 марта 2017, 07:18
0

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

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

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

    James Black04 ноября 2009, 03:17
  • Я согласен, если вы не хотите повторять, не используйте коллекцию.Вместо этого используйте другой, более конкретный интерфейс.

    Adeel Ansari04 ноября 2009, 02:41
  • Мне интересно… допустим, фактические базовые данные - это SortedSet, поэтому порядок имеет смысл, но у вас есть только представление Collection (например, по не глупой причине);если вы поместите коллекцию в список, очередь и т. д. и попытаетесь получить / опросить / и т. д., произойдет ли катастрофа?Точно так же, если основная структура - это список и т. Д.

    Carl04 ноября 2009, 03:15
0

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

 Collection<String> getStrings();
 

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

 List<String> listString = (List) getStrings();
String firstElement = (listString.isEmpty() ? null : listString.get(0));
 
2

В Java 8 у вас есть несколько операторов, например limit

      /**
 * 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);
}
 

  • Ответ @Vitalii Федоренко http://stackoverflow.com/a/18165855/1562662 лучше.

    Chacko Mathew09 марта 2017, 07:26
446

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

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

Отличный вопрос ... Поначалу кажется, что интерфейс Collection упущен.

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

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

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

Убедитесь, что вы проверили возврат iterator(), поскольку он может быть пустым или null в зависимости от реализации.

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

    Next Developer16 января 2019, 19:35
  • Это должен быть правильный ответ.Я не понимаю, почему ответ всегда «используйте другую библиотеку!».

    Kuzeko18 мая 2016, 14:44
  • Важно отметить, что этот «трюк» работает только тогда, когда коллекция действительно имеет содержимое.Если он пуст, итератор может вернуть ошибку, при которой необходимо заранее проверить размер коллекции.

    spaceemotion06 ноября 2015, 17:05
  • Как насчет второго элемента коллекции?Почему first-> next () не работает?Что я должен делать?Спасибо!

    pb77218 мая 2017, 07:42
-2

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

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

Документация javadoc для Collection дает следующее предостережение относительно порядка элементов массива:

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

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

    Jim Ferrans04 ноября 2009, 02:46
  • Я пришел сюда, потому что это было решение, которое я нашел уродливым.

    haansn0808 августа 2014, 22:05
  • Да, я подумал об этом после того, как разместил это.Независимо от используемого метода упорядочение зависит от базовой реализации Collection.Тогда «первый» становится относительным термином.

    Однако в большинстве случаев лучше использовать метод iterator ().

    Andy Gherna04 ноября 2009, 13:38
0

Функциональный способ:

 public static <T> Optional<T> findFirst(List<T> result) {
    return Optional.ofNullable(result)
            .map(List::stream)
            .flatMap(Stream::findFirst);
}
 

Сохранение фрагмента кода выше из исключений NullPointerException и IndexOutOfBoundsException

40

В Collection нет такого понятия, как "первый" элемент, потому что это ... ну просто коллекция.

Из коллекции документа Java.Метод iterator () :

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

Значит, нельзя.

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

 String first = strs.get(0);
 

Но напрямую из Коллекции это невозможно.

  • @arghena: Ага.Я обновил ответ, чтобы подчеркнуть альтернативу.

    OscarRyz04 ноября 2009, 02:40
  • также, если вы знаете , что в коллекции будет только один элемент, тогда имеет смысл получить первый ;-)

    Brad Parks22 марта 2012, 18:48
  • @Oscar: извините, я должен был опубликовать сообщение до того, как увидел ваше изменение (я думал, что мой комментарий был первым).Мой браузер, должно быть, работал медленно: P

    Andy Gherna04 ноября 2009, 13:39
  • Вы правы, я упустил этот момент.Я обновил ответ.Вы не можете!(если Коллекция не реализована каким-либо базовым классом, который позволяет предоставлять гарантию)

    OscarRyz04 ноября 2009, 02:33
  • Хорошее замечание.Но иногда бывает необходимо вытащить какой-нибудь случайный.Даже если «первый» не всегда один и тот же, преимущество знания его первого заключается в том, что вы будете знать (или, по крайней мере, надеяться, что не эксперт по Java), что вся коллекция была повторена, тратя ресурсы и время..

    Doug Molineux28 марта 2011, 19:57
  • -1: n-й элемент из Iterable легко определить.При работе с List у вас есть дополнительные гарантии, что операция стабильна (и часто может быть выполнена за время O (1)), но это не меняет определения n-го элемента Iterable.

    Sam Harwell30 сентября 2011, 14:19
  • Может быть, но рассмотрим случай, когда вы добавляете новый элемент в коллекцию, вы не знаете (по интерфейсу), является ли этот элемент первым, последним или он будет вставлен посередине.Для точных результатов вам следует использовать другой интерфейс.Тем не менее, вероятно, что Розарху нужен первый элемент, несмотря ни на что.Знание коллекции подложки может помочь, но помешает вам изменить ее.

    OscarRyz04 ноября 2009, 17:49
  • Оскар, я думаю, вы преувеличиваете.Первый элемент Collection может быть произвольным в некоторых случаях, таких как HashSet, но он четко определен: это .iterator (). Next ().Кроме того, он стабилен во всех реализациях коллекции, которые я когда-либо видел.

    (связано: обратите внимание, что, хотя Set не гарантирует порядок, каждый подтип Set в JDK, кроме HashSet, гарантирует.)

    Kevin Bourrillion04 ноября 2009, 16:54
  • get отсутствует в интерфейсе коллекции

    Andy Gherna04 ноября 2009, 02:33
  • Я не думаю, что get(int n) определен для Collection

    Nick Heiner04 ноября 2009, 02:27