Java:从集合中获取第一项
如果我有一个收藏,例如Java:从集合中获取第一项,java,collections,iterable,Java,Collections,Iterable,如果我有一个收藏,例如收藏STR,如何取出第一个项目?我可以调用一个迭代器,取下它的第一个next(),然后扔掉迭代器。有没有一种不那么浪费的方法呢?在集合中没有“第一”项,因为它是。。好吧,这只是一个收藏 从Java文档的方法: 没有关于元素返回顺序的保证 所以你不能 如果使用另一个界面,如列表,则可以执行以下操作: String first = strs.get(0); 但直接从集合中执行此操作是不可能的。您可以执行以下操作: String strz[] = strs.toArray(St
收藏STR
,如何取出第一个项目?我可以调用一个迭代器
,取下它的第一个next()
,然后扔掉迭代器。有没有一种不那么浪费的方法呢?在集合中没有“第一”项,因为它是。。好吧,这只是一个收藏
从Java文档的方法:
没有关于元素返回顺序的保证
所以你不能
如果使用另一个界面,如列表,则可以执行以下操作:
String first = strs.get(0);
但直接从集合中执行此操作是不可能的。您可以执行以下操作:
String strz[] = strs.toArray(String[strs.size()]);
String theFirstOne = strz[0];
集合的javadoc对数组元素的排序给出了以下警告:
如果此集合保证迭代器返回元素的顺序,则此方法必须以相同的顺序返回元素
看起来这是最好的方法:
String first = strs.iterator().next();
好问题。。。起初,这似乎是对集合
接口的疏忽
请注意,“first”并不总是返回您放入集合中的第一个内容,并且可能仅对有序集合有意义。也许这就是为什么没有get(item)
调用的原因,因为顺序不一定被保留
虽然这看起来有点浪费,但可能并不像你想象的那么糟糕。迭代器实际上只包含集合中的索引信息,而不是整个集合的副本。调用此方法确实实例化了迭代器
对象,但这实际上是唯一的开销(与复制所有元素不同)
例如,查看ArrayList.iterator()
方法返回的类型,我们看到它是ArrayList::Itr
。这是一个内部类,它只直接访问列表中的元素,而不是复制它们
只需确保检查iterator()
的返回,因为它可能是空的或null
,具体取决于实现。如果您知道集合是一个队列,那么您可以将集合强制转换为一个队列并轻松获取它
您可以使用几种结构来获取订单,但您需要对其进行转换。听起来您的收藏想要列表式的,因此我建议:
List<String> myList = new ArrayList<String>();
...
String first = myList.get(0);
List myList=new ArrayList();
...
String first=myList.get(0);
因为实际上,如果您使用的是集合,那么您应该使用Google Collections。在java 8中:
Optional<String> firstElement = collection.stream().findFirst();
这完全取决于您使用的实现,是arraylist linkedlist还是set的其他实现
如果设置了它,那么您可以直接获取第一个元素,它们可以在集合上进行技巧循环,创建一个值为1的变量,并在中断该循环后在标志值为1时获取值
如果它是list的实现,那么定义索引号就很容易了。在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);
}
/**
*限制通过管道排放的项目总数的运算符
*将打印
* [1]
*@抛出中断异常
*/
@试验
public void limitStream()引发InterruptedException{
列表=数组.asList(1,2,3,1,4,2,3)
.stream()
.限额(1)
.collect(toList());
系统输出打印项次(列表);
}
您可以进行铸造。例如,如果存在一个具有此定义的方法,并且您知道此方法正在返回列表:
Collection<String> getStrings();
Collection getStrings();
调用它之后,您需要第一个元素,您可以这样做:
List<String> listString = (List) getStrings();
String firstElement = (listString.isEmpty() ? null : listString.get(0));
List listString=(List)getStrings();
String firstElement=(listString.isEmpty()?null:listString.get(0));
番石榴提供了一个onlyElement
收集器
,但仅当您希望该集合只有一个元素时才使用它
Collection<String> stringCollection = ...;
String string = collection.stream().collect(MoreCollectors.onlyElement())
功能方式:
public static <T> Optional<T> findFirst(List<T> result) {
return Optional.ofNullable(result)
.map(List::stream)
.flatMap(Stream::findFirst);
}
public静态可选findFirst(列表结果){
返回可选的。不可用的(结果)
.map(列表::流)
.flatMap(流::findFirst);
}
上面的代码片段reserve from NullPointerException和IndexOutOfBoundsException我不认为get(int n)
是为Collection定义的
你说得对,我忽略了这一点。我已经更新了答案。你不能!(除非集合是由某个允许提供保证的底层类实现的)get不在集合接口中,我认为您夸大了情况。集合的第一个元素在HashSet等少数情况下可能是任意的,但它是定义良好的:它是.iterator().next()。在我见过的每个集合实现中,它都是稳定的。(相关:请注意,虽然SET不能保证顺序,JDK中除HasSet之外的每一个子集都是如此)。但是,考虑到在向集合中添加新元素时的情况,您不知道(通过接口)如果该元素是第一个、最后一个,或者它将被插入中间。为了获得精确的结果,您应该使用另一个界面。然而,不管怎样,罗萨奇所需要的可能是第一要素。了解基线集合可能会有所帮助,但它会阻止您更改它。我同意,如果您不想迭代,请不要使用集合。使用其他更具体的接口。我想知道……假设实际的底层数据是一个SortedSet,所以顺序是有意义的,但您只有它的集合视图(比如说,出于一个非愚蠢的原因);如果您将集合强制转换为列表、队列等,并尝试获取/poll/etc,是否会发生灾难?同样,如果底层结构是一个列表,依此类推。@Cal-我还没有尝试过,但如果您将集合强制转换为一个非常不同的类型,则
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);
}