Bir diziden akış yaparken neden tam sayıları dizelerle eşleyemiyorum?


94

Bu kod çalışır (Javadoc'ta alınmıştır):

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

Bu derlenemez:

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

IDEA bana "lambda ifadesinde uyumsuz bir dönüş türü String" olduğunu söylüyor.

Neden ? Ve bunu nasıl düzeltebilirim?

Yanıtlar:


121

Arrays.stream(int[])IntStreama değil, bir oluşturur Stream<Integer>. Yani bir nesneyi bir nesneye eşlerken mapToObjsadece çağırmak yerine çağırmanız gerekir .mapint

Bu beklendiği gibi çalışmalıdır:

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

ayrıca yazabilirsiniz:

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

3
Arasındaki fark nedir IntStreamve Stream<Integer>?
Florian Margaine

8
@FlorianMargaine An IntStream, ilkel intdeğerler için bir akış uzmanlığıdır . A Stream<Integer>sadece Integernesneleri tutan bir Akımdır.
Alexis C.

2
@FlorianMargaine IntStreambir akış veya ilkel (ints), oysa Steram<Integer>bir nesne akışıdır. İlkel akışların performans nedenleriyle özel yöntemleri vardır.
assylias

7
IntStream.mapToObjIntFunctionbir intdeğer  tüketen bir işlev beklediğinden .mapToObj((Integer i) -> i.toString())çalışmaz. Ondan gereksiz bir dönüşüm içerir gibi önerilen zaten olmazdı intiçin Integer. Buna karşılık, yöntemi .mapToObj(Integer::toString)çağıracağı için güzel çalışır . Bu çağrılmasına farklı olduğunu Not a üzerinde  o belirsiz olduğundan derlemek olmaz ikincisi olarak. staticInteger.toString(int).map(Integer::toString)Stream<Integer>
Holger

1
@cic: hayır, çağıran .map(Integer::toString)bir üzerinde Stream<Integer>hem de gerçekten belirsiz, .map(i->i.toString())ve .map(i->Integer.toString(i))geçerlidir. Ancak kullanılarak kolayca çözülebilir .map(Object::toString).
Holger

19

Arrays.stream(numbers)bir IntStreambaşlık altında bir oluşturur ve bir üzerinde harita operasyonu bir IntStreamgerektirir IntUnaryOperator(yani bir fonksiyon int -> int). Uygulamak istediğiniz eşleme işlevi bu sözleşmeye ve dolayısıyla derleme hatasına uymuyor.

Bir boxed()almak için önce aramanız gerekir Stream<Integer>( Arrays.asList(...).stream()geri dönen şey budur ). Ardından map, ilk parçada yaptığınız gibi arayın .

boxed()Bunu takip etmeniz gerekiyorsa, mapmuhtemelen mapToObjdoğrudan kullanmak isteyeceğinizi unutmayın .

Avantajı, mapToObjher bir intdeğeri bir Integernesneye yerleştirmeyi gerektirmemesidir; tabi ki uyguladığınız eşleme işlevine bağlı olarak; bu yüzden yazmak için daha kısa olan bu seçeneği tercih ederim.


5

Arrays.stream (int []) kullanarak bir Tamsayı Akışı yaratabilir, mapToObjbeğenebilirsiniz mapToObj(Integer::toString).

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

Bu yardımcı olur umarım..


2

Boks, AFAIK ve yığına küçük ip patlaması eklenmedi:

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

1

Bu örneğin ve sorunun amacı, dizeleri bir int akışıyla nasıl eşleştireceğinizi bulmaksa (örneğin, bir dizi dizisindeki bir dizine erişmek için bir giriş akışı kullanarak), kutuyu da kullanabilir ve ardından int (daha sonra dizinin dizinine erişime izin verir).

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

.Boxed () çağrısı, IntStream'inizi (ilkel girişlerin bir akışını) bir Akışa (nesnelerin bir akışına - yani, Tamsayı nesnelerine) dönüştürür ve bu daha sonra bir nesnenin (bu durumda, bir String nesnesi) dönüşünü kabul eder. lambda'nız. Burada, gösterme amacıyla sayının yalnızca bir dize temsilidir, ancak daha önce bahsedildiği gibi bir dizgi dizisinin öğesi gibi, herhangi bir dize nesnesi de kolayca (ve daha pratik olarak) olabilir.

Başka bir olasılık sunacağımı düşündüm. Programlamada, bir görevi gerçekleştirmenin her zaman birden fazla yolu vardır. Yapabildiğiniz kadar çok şey öğrenin, ardından performans sorunlarını, sezgiselliği, kodun netliğini, kodlama stilindeki tercihlerinizi ve en çok kendi kendini belgelendirmeyi göz önünde bulundurarak elinizdeki göreve en uygun olanı seçin.

Mutlu kodlamalar!


1
Gereksiz iş yapıyorsun. Her intbirini kendi sarmalayıcı türüne Integerkoyarsınız ve hemen sonra kutusundan çıkarırsınız.
Alexis C.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.