Java:コレクションから最初のアイテムを取得する


277

などのコレクションがある場合Collection<String> strs、どのようにして最初のアイテムを入手できますか?私は単にを呼び出し、Iterator最初next()にを取り、次に捨てIteratorます。無駄を省く方法はありますか?


1
もちろん、実装するコンテナクラスを知っている場合は、最初の要素にアクセスするためのより良い方法があるかもしれません...
Rooke


1
Queue.peek()が必要なようです
ヨハネス

回答:


131

Iterables.get(yourC、indexYouWant)

というのも、コレクションを使用している場合は、Googleコレクションを使用する必要があるからです。


7
これは同じことを行います。最初にリストであるかどうかを確認し、リストである場合はインデックスで取得します。また、実際のコレクションでより速く失敗しようとするコードもあります(つまり、インデックスが大きすぎる場合は、全体を繰り返し処理せずに、最後に例外をスローせずにそれを理解しようとします)。
Yishai、

1
正直なところ、パフォーマンスの点ではc.iterator()。next()よりも少し遅いかもしれませんが、コードはより明確で変更が簡単です。
カール

2
私はそれがよりクリーンであることに確かに同意しますが、OPは無駄でしたが、あなたの答えが受け入れられたので、それは望まれたことだと思います。
Yishai、

8
(まだ)ここに到着した場合:jheddingsの答えはおそらく「それを実現する」ための最良の答えだと思いますが、GCライブラリを既に使用している場合は、@ DonaldRaab(ページの途中)のほうがいいと思います。私の答えは本当に、後で柔軟性を持たせたい場合(たとえば、2番目の要素が新しいホットネスであると判断した場合)です。
カール

4
場合によっては、コレクションを使用するコードを使用しているだけなので、実行することはあまりありません。
erickrf 2015

436

それがそれを行うための最良の方法であるように見えます:

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

すばらしい質問...最初は、Collectionインターフェースの見落としのようです。

「first」は常にコレクションに最初に置いたものを返すとは限らず、順序付けられたコレクションに対してのみ意味があることに注意してください。get(item)注文が必ずしも保持されるわけではないので、たぶんそれが呼び出しがない理由です。

それは少し無駄に見えるかもしれませんが、あなたが思うほど悪くはないかもしれません。Iterator本当にただのコレクション、コレクション全体のない通常コピーにインデックス情報が含まれています。このメソッドを呼び出すとIteratorオブジェクトがインスタンス化されますが、それが実際に唯一のオーバーヘッドです(すべての要素をコピーするようなものではありません)。

たとえば、ArrayList<String>.iterator()メソッドによって返された型を見ると、それがであることがわかりArrayList::Itrます。これは、リストの要素をコピーするのではなく、直接アクセスするだけの内部クラスです。

iterator()空であるかnull、実装に依存している可能性があるため、の戻り値を確認してください。


3
この「トリック」は、コレクションに実際にコンテンツがある場合にのみ機能することに注意してください。空の場合、イテレータはエラーを返す可能性があり、事前にコレクションサイズを確認する必要があります。
spaceemotion 2015年

20
これが正解です。答えが常に「別のライブラリを使用する」である理由がわかりません。。
Kuzeko 2016年

コレクションの2番目の要素はどうですか?first-> next()が機能しないのはなぜですか?私は何をすべきか?ありがとう!
pb772

安全性が十分ではありません。コレクションが常に最初の要素を指すとは限りません。
次の開発者

84

Java 8の場合:

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

古いバージョンのJavaでは、Guava Iterablesに getFirstメソッドがあります

Iterables.getFirst(iterable, defaultValue)

6
java 8ソリューションは、コレクションが空であるケースを適切に処理するため、特に便利です。
SpaceTrucker 2016

4
良くない。4行のコードを書くのが面倒なので、stream()のオーバーヘッドを追加してget(0)を取得します。if(!CollectionUtils.isEmpty(productList)){return Optional.of(productList.get(0)); } return Optional.empty();
RS

getFirst利用できる方法がありません。ありgetgetLast方法
user1209216 2017

4
@RSであり、コレクションなので、productList.get(0)を呼び出せない場合はどうなりますか?(OPの質問による)
Denham Coote 2017年

40

Collection単なるコレクションなので、「最初の」アイテムなどはありません。

Java docのCollection.iterator()メソッドから:

要素が返される順序に関する保証はありません...

だからできません。

Listなどの別のインターフェースを使用する場合は、次のことができます。

String first = strs.get(0);

しかし、コレクションから直接これを行うことはできません。


11
get(int n)定義されているとは思いませんCollection
Nick Heiner

2
あなたは正しい、私はその点を逃しています。答えを更新しました。できません!(コレクションが保証を提供できるいくつかの
基礎となる

getはCollectionインターフェースにありません
Andy Gherna 2009年

21
オスカー、あなたは事件を過大評価していると思います。コレクションの最初の要素は、HashSetのようないくつかのケースでは任意である可能性がありますが、明確に定義されています。それは.iterator()。next()です。また、これまでに見たすべてのコレクション実装で安定しています。(関連:Setは順序を保証しないが、HashSetを除くJDK内のすべての単一のサブタイプがそうであることに注意してください。)
Kevin Bourrillion

3
そうかもしれませんが、コレクションに新しい要素を追加するときに、その要素が最初であるか、最後であるか、または途中に挿入されるかが(インターフェイスでは)わからない場合を考慮してください。正確な結果を得るには、別のインターフェースを使用する必要があります。しかし、おそらくRosarchに必要なのは、何があっても最初の要素です。基になるコレクションを知っていると役立つ場合がありますが、変更できなくなります。
OscarRyz 2009年

4

あなたのコレクションはリストのようなものにしたいので、私は次のことを提案します。

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

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

2
@Vitalii Fedorenkoの回答stackoverflow.com/a/18165855/1562662の方が優れています。
Chacko Mathew 2017

2

Guavaはを提供しonlyElement Collectorますが、コレクションに要素が1つだけあると予想される場合にのみ使用します。

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

要素の数がわからない場合は、を使用してくださいfindFirst

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

1

キャストできます。たとえば、この定義を持つ1つのメソッドが存在し、このメソッドがリストを返すことがわかっている場合:

Collection<String> getStrings();

そしてそれを呼び出した後、最初の要素が必要です、あなたはこのようにそれを行うことができます:

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

0

コレクションがキューであることを知っている場合は、コレクションをキューにキャストして簡単に取得できます。

注文を取得するために使用できる構造がいくつかありますが、それにキャストする必要があります。


繰り返したくない場合は、コレクションを使用しないでください。代わりに、他のより具体的なインターフェイスを使用してください。
Adeel Ansari、

1
しかし、実際の基になるデータはSortedSetであるとしましょう。したがって、順序は理にかなっていますが、コレクションビューしかありません(ばかげていない理由のために考えてみましょう)。コレクションをリスト、キューなどにキャストしてget / poll / etcを実行しようとすると、災害が発生しますか?同様に、基になる構造がリストである場合なども同様です。
カール、

@Cal-試したことはありませんが、コレクションを元のタイプと大きく異なるタイプにキャストすると、エラーが発生するはずですが、試したことがないので、間違っている可能性があります。
James Black、

0

これは、使用した実装、arraylist linkedlist、または他のsetの実装に完全に依存します。

これが設定されている場合、最初の要素を直接取得できます。それらは、コレクションに対するトリックループであり、値1の変数を作成し、そのループを解除した後、フラグ値が1のときに値を取得します。

リストの実装であれば、インデックス番号を定義することで簡単です。


0

機能的な方法:

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

上記のコードスニペットは、NullPointerExceptionおよびIndexOutOfBoundsExceptionから保持されます。


1
の選択は、でList<T>機能するという条件を満たしていませんCollection<String>が、もちろん、を使用Collection<T>して修正することができ、追加の変更が必要です.map(Collection::stream)
スクラッチ

-2

あなたはこれを行うことができます:

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

コレクションのjavadocは、配列の要素の次の警告wrt順序を提供します。

このコレクションが反復子によって要素が返される順序について保証する場合、このメソッドは要素を同じ順序で返す必要があります。


2
これにより、新しいString配列が作成されます。イテレータを作成するよりもはるかにコストがかかります。
ジムフェラン2009年

ええ、私はこれを投稿した後、それについて考えました。使用される方法に関係なく、順序付けは、基になるコレクションの実装に依存します。「最初」は相対的な用語になります。ただし、ほとんどの場合、iterator()を使用する方がおそらく良いでしょう。
アンディガーナ2009年

2
これが私が持っていて醜い解決策だったので、私はここに来ました。
haan​​sn08 2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.