Java:从集合中获取第一项

如果我有一个集合,比如Collection<String> strs,我如何取出第一项?我可以调用一个Iterator,取它的第一个next(),然后扔掉Iterator。有没有更少浪费的方法呢?

469575 次浏览

Collection中没有这样的“first”项,因为它是。嗯,只是一个集合。

从Java文档的Collection.iterator ()方法:

没有关于元素返回顺序的保证。

所以你不能。

如果你使用另一个接口,比如列表,你可以做以下事情:

String first = strs.get(0);

但直接从一个集合这是不可能的。

你可以这样做:

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

javadoc for Collection给出了如下数组元素的顺序:

如果该集合对其迭代器返回元素的顺序有任何保证,则该方法必须以相同的顺序返回元素。

看起来这是最好的方法:

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

好问题……起初,它似乎是Collection接口的一个疏忽。

请注意,“first”并不总是返回您放入集合中的第一个东西,并且可能只对有序集合有意义。也许这就是为什么没有get(item)调用的原因,因为顺序不一定被保留。

虽然这看起来有点浪费,但可能没有你想的那么糟糕。Iterator实际上只包含索引信息到集合中,通常不是整个集合的副本。调用此方法确实实例化了Iterator对象,但这实际上是唯一的开销(不像复制所有元素)。

例如,查看ArrayList<String>.iterator()方法返回的类型,我们看到它是ArrayList::Itr。这是一个内部类,它直接访问列表中的元素,而不是复制它们。

只要确保你检查了iterator()的返回值,因为它可能是空的,也可能是null,这取决于实现。

如果知道集合是队列,则可以将集合强制转换为队列并轻松获取它。

您可以使用几个结构来获得订单,但需要对其进行强制转换。

听起来你的Collection想要像list一样,所以我建议:

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

在java 8中:

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

对于旧版本的java,在Guava iterable中有一个getFirst方法:

Iterables.getFirst(iterable, defaultValue)

这完全取决于你使用的是哪种实现,是arraylist linkedlist,还是set的其他实现。

如果它被设置了,那么你可以直接获得第一个元素,它们可以在集合上进行诡计循环,创建一个值为1的变量,当标志值为1时获得值,然后打破循环。

如果是列表的实现,那么通过定义索引号很容易。

在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);
}

你可以选角。例如,如果存在一个具有此定义的方法,并且您知道该方法将返回一个List:

Collection<String> getStrings();

调用它之后,你需要第一个元素,你可以这样做:

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

Guava提供了onlyElement Collector,但只有在期望集合只有一个元素时才使用它。

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

如果你不确定有多少元素,使用findFirst

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

功能:

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

上面的代码片段保留NullPointerException和IndexOutOfBoundsException

我用了这个:

strs.isEmpty() ? "" : strs.iterator().next();

😄

如果你正在使用Apache Commons Collections 4,有一个IterableUtils.first方法。它在__abc1的情况下包含了一个优化,使用起来很整洁。这和番石榴法很相似。代码看起来像

String firstStr = IterableUtils.first(strs);