web-dev-qa-db-ja.com

配列からストリーミングするときに整数を文字列にマッピングできないのはなぜですか?

このコードは機能します(Javadocで取得):

List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
    .map(i -> i.toString())
    .collect(Collectors.joining(", "));

これはコンパイルできません:

int[] numbers = {1, 2, 3, 4};
String commaSeparatedNumbers = Arrays.stream(numbers)
    .map((Integer i) -> i.toString())
    .collect(Collectors.joining(", "));

IDEAは、「ラムダ式に互換性のない戻り値型の文字列がある」と言っています。

どうして ?そしてそれを修正する方法は?

83
Denys Séguret

Arrays.stream(int[])は、Stream<Integer>ではなく、IntStreamを作成します。したがって、mapToObjをオブジェクトにマッピングするときは、mapの代わりに int を呼び出す必要があります。

これは期待どおりに機能するはずです。

String commaSeparatedNumbers = Arrays.stream(numbers)
    .mapToObj(i -> ((Integer) i).toString()) //i is an int, not an Integer
    .collect(Collectors.joining(", "));

あなたはまた書くことができます:

String commaSeparatedNumbers = Arrays.stream(numbers)
    .mapToObj(Integer::toString)
    .collect(Collectors.joining(", "));
104
assylias

Arrays.stream(numbers)はフードの下にIntStreamを作成し、IntStreamのマップ操作にはIntUnaryOperator(つまり、関数int -> int)が必要です。適用するマッピング関数はこのコントラクトを尊重しないため、コンパイルエラーが発生します。

Stream<Integer>を取得するために、事前にboxed()を呼び出す必要があります(これはArrays.asList(...).stream()が返すものです)。次に、最初のスニペットで行ったようにmapを呼び出します。

boxed()に続いてmapが必要な場合は、おそらくmapToObjを直接使用することに注意してください。

利点は、mapToObjが各int値をIntegerオブジェクトにボックス化する必要がないことです。もちろん適用するマッピング関数に応じて。だから私はこのオプションを選択します。

19
Alexis C.

Arrays.stream(int [])を使用して整数ストリームを作成でき、mapToObj(Integer::toString)のようなmapToObjを呼び出すことができます。

String csn = Arrays.stream(numbers) // your numbers array
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));

お役に立てれば..

5
codebot

このサンプルと質問の目的が文字列をintのストリームにマップする方法を理解することである場合(たとえば、intのストリームを使用して文字列の配列のインデックスにアクセスする場合)、ボクシングを使用してキャストすることもできますint(配列のインデックスへのアクセスを許可します)。

int[] numbers = {0, 1, 2, 3}; 
String commaSeparatedNumbers = Arrays.stream(numbers)
    .boxed()
    .map((Integer i) -> Integer.toString((int)i))
    .collect(Collectors.joining(", "));

.boxed()呼び出しは、IntStream(プリミティブなintのストリーム)をStream(オブジェクトのストリーム、つまりIntegerオブジェクト)に変換し、その後、オブジェクト(この場合はStringオブジェクト)の戻り値を受け入れますあなたのラムダ。ここでは、デモンストレーション用の数字の文字列表現にすぎませんが、前述の文字列配列の要素のように、任意の文字列オブジェクトと同じくらい簡単に(そしてより実際的に)使用できます。

別の可能性を提供すると思いました。プログラミングでは、タスクを達成する複数の方法が常にあります。できるだけ多くのことを知ってから、パフォーマンスの問題、直感性、コードの明快さ、コーディングスタイルの好み、そして最も自己文書化を念頭に置いて、手元のタスクに最適なものを選択します。

ハッピーコーディング!

1
jamesc1101

ボクシングなし、見知らぬ人、およびヒープに追加された小さな文字列の爆発なし:

public static void main(String[] args) {
    IntStream stream = IntStream.of(1, 2, 3, 4, 5, 6);
    String s = stream.collect(StringBuilder::new, (builder, n) -> builder.append(',').append(n), (x, y) -> x.append(',').append(y)).substring(1);
    System.out.println(s);
}
0
AbuNassar