Если у меня есть коллекция, например Collection<String> strs
, как я могу достать первый предмет? Я мог бы позвонить Iterator
, взять ее сначала next()
, а потом выбросить Iterator
. Есть ли менее расточительный способ сделать это?
Если у меня есть коллекция, например Collection<String> strs
, как я могу достать первый предмет? Я мог бы позвонить Iterator
, взять ее сначала next()
, а потом выбросить Iterator
. Есть ли менее расточительный способ сделать это?
Ответы:
Iterables.get (yourC, indexYouWant)
Потому что на самом деле, если вы используете Коллекции, вы должны использовать Google Коллекции.
Похоже, это лучший способ сделать это:
String first = strs.iterator().next();
Отличный вопрос ... На первый взгляд это похоже на недосмотр Collection
интерфейса.
Обратите внимание, что «first» не всегда возвращает первое, что вы положили в коллекцию, и может иметь смысл только для упорядоченных коллекций. Может быть, поэтому нет get(item)
звонка, поскольку порядок не обязательно сохраняется.
Хотя это может показаться немного расточительным, это может быть не так плохо, как вы думаете. На Iterator
самом деле просто содержит информацию индексации в коллекции, а не копию всего собрания. Вызов этого метода создает экземпляр Iterator
объекта, но на самом деле это единственные накладные расходы (не как копирование всех элементов).
Например, глядя на тип, возвращаемый ArrayList<String>.iterator()
методом, мы видим, что это так ArrayList::Itr
. Это внутренний класс, который просто обращается к элементам списка напрямую, а не копирует их.
Просто убедитесь, что вы проверили возврат, iterator()
поскольку он может быть пустым или null
зависеть от реализации.
В Java 8:
Optional<String> firstElement = collection.stream().findFirst();
Для более старых версий java есть метод getFirst в Guava Iterables :
Iterables.getFirst(iterable, defaultValue)
getFirst
доступных методов. Есть get
и getLast
методы
Не существует такого понятия, как «первый» элемент, Collection
потому что это .. ну, просто коллекция.
Из метода Collection.iterator () Java-документа :
Нет никаких гарантий относительно порядка, в котором элементы возвращаются ...
Так что ты не можешь.
Если вы используете другой интерфейс, например List , вы можете сделать следующее:
String first = strs.get(0);
Но прямо из Коллекции это невозможно.
get(int n)
определено дляCollection
Похоже, ваша коллекция хочет быть похожей на список, поэтому я бы предложил:
List<String> myList = new ArrayList<String>();
...
String first = myList.get(0);
В 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);
}
Guava предоставляет onlyElement
Collector
, но использует его, только если вы ожидаете, что в коллекции будет ровно один элемент.
Collection<String> stringCollection = ...;
String string = collection.stream().collect(MoreCollectors.onlyElement())
Если вы не знаете, сколько там элементов, используйте findFirst
.
Optional<String> optionalString = collection.stream().findFirst();
Вы можете сделать кастинг. Например, если существует один метод с этим определением, и вы знаете, что этот метод возвращает список:
Collection<String> getStrings();
И после вызова вам нужен первый элемент, вы можете сделать это так:
List<String> listString = (List) getStrings();
String firstElement = (listString.isEmpty() ? null : listString.get(0));
Если вы знаете, что коллекция является очередью, вы можете легко преобразовать ее в очередь.
Есть несколько структур, которые вы можете использовать, чтобы получить заказ, но вам нужно будет привести его к нему.
Это полностью зависит от того, какую реализацию вы использовали, будь то ArrayList связанный список или другие реализации набора.
если он установлен, то вы можете напрямую получить первый элемент, их можно сделать цикличным циклом по коллекции, создать переменную со значением 1 и получить значение, когда значение флага равно 1, после того, как этот цикл прервется.
если это реализация списка, то это легко определить с помощью индекса.
Функциональный способ:
public static <T> Optional<T> findFirst(List<T> result) {
return Optional.ofNullable(result)
.map(List::stream)
.flatMap(Stream::findFirst);
}
Приведенный выше фрагмент кода сохраняется из NullPointerException и IndexOutOfBoundsException
List<T>
не удовлетворяет условие , что он должен работать для Collection<String>
, но, конечно, может быть закреплена с помощью Collection<T>
, с дополнительным изменением: .map(Collection::stream)
.
Вы могли бы сделать это:
String strz[] = strs.toArray(String[strs.size()]);
String theFirstOne = strz[0];
Javadoc для Collection дает следующее предостережение относительно упорядочивания элементов массива:
Если эта коллекция дает какие-либо гарантии относительно того, в каком порядке ее элементы возвращаются ее итератором, этот метод должен возвращать элементы в том же порядке.