Nasıl Java 8 Stream Array dönüştürmek için?


775

Java 8'i Streambir diziye dönüştürmenin en kolay / en kısa yolu nedir?


2
Soru daha eksiksiz olduğu ve bir şey denediğinizi gösterdiği için geri dönüşü geri döndürmenizi öneririm.
skiwi

2
@skiwi Teşekkürler! ama denenen kod gerçekten soruya daha fazla bilgi eklemediğini düşündüm ve hiç kimse "bize girişiminizi gösterin" diye bağırdı henüz =)

17
@skiwi: Genellikle benim yerine ödevimi yap sorularına bağırmamla birlikte, bu özel soru daha fazla karışıklık olmadan bana daha açık görünüyor. Bunu düzenli tutalım.
Honza Zidek

Paketin resmi belgelerinde birçok yanıt ve rehberlik bulabilirsiniz: docs.oracle.com/javase/8/docs/api/java/util/stream/…
Christophe Roussy

Yanıtlar:


1168

En kolay yöntem toArray(IntFunction<A[]> generator)yöntemi dizi yapıcı başvurusuyla kullanmaktır. Bu, yöntemin API belgelerinde önerilir .

String[] stringArray = stringStream.toArray(String[]::new);

Yaptığı şey, bir tamsayıyı (boyut) argüman olarak alan ve String[]tam olarak (aşırı yüklerden birinin) new String[]yaptığı a döndüren bir yöntem bulmaktır .

Ayrıca kendiniz de yazabilirsiniz IntFunction:

Stream<String> stringStream = ...;
String[] stringArray = stringStream.toArray(size -> new String[size]);

Bunun amacı IntFunction<A[]> generator, dizinin boyutu olan bir tamsayıyı yeni bir diziye dönüştürmektir.

Örnek kod:

Stream<String> stringStream = Stream.of("a", "b", "c");
String[] stringArray = stringStream.toArray(size -> new String[size]);
Arrays.stream(stringArray).forEach(System.out::println);

Baskılar:

a
b
c

8
ve Array yapıcı başvurusunun neden ve nasıl çalıştığını gösteren bir açıklama: stackoverflow.com/questions/29447561/…
jarek.jpa

"Zenexer doğru, çözüm şöyle olmalıdır: stream.toArray (String [] :: new);" ... Peki tamam, ama bir yöntem referans mantıklı ve işlevsel olarak eşdeğer olduğunu anlamalıyım, bu toArray(sz -> new String[sz])yüzden gerçekten çözümün ne olması gerektiğini ya da olması gerektiğini söyleyebilir emin değilim.
scottb

3
@scottb sz -> new String[sz], yapıcı başvurusunun yapmadığı yeni bir işlev yapar. Sanırım çöp toplama karmaşasına ne kadar değer verdiğinize bağlı.
WORMSS

3
@WORMSS Olmaz. O (statik olarak!), Karmaşaya neden olmayan yeni bir private yöntem yapar ve her iki sürümün de yeni bir nesne oluşturması gerekir. Bir başvuru, doğrudan hedef yönteme işaret eden bir nesne oluşturur; lambda üretilen nesneyi gösteren bir nesne yaratır private. Bir kurucuya yapılan göndermenin, dolaylı eksiklik ve daha kolay VM optimizasyonu için hala daha iyi performans göstermesi gerekir, ancak çalkalamanın bununla hiçbir ilgisi yoktur.
HTNW

2
@HTNW haklısın özür dilerim. Bunu ilk denemede çalkalanmaya neden olan karmaşaya neden olan hata ayıklama girişimim tam da bu oldu, bu yüzden kafamda böyle olduğunu fark ettim. (Bu olduğu zaman nefret ediyorum).
WORMSS

41

Bir Akıştan 1 ile 10 arasında bir değer içeren bir dizi içe almak istiyorsanız, elinizde IntStream vardır.

Burada bir Stream.of yöntemiyle bir Akış oluşturuyoruz ve bir Akışı bir mapToInt kullanarak IntStream'e dönüştürüyoruz. Sonra IntStream'in toArray yöntemini çağırabiliriz.

Stream<Integer> stream = Stream.of(1,2,3,4,5,6,7,8,9,10);
//or use this to create our stream 
//Stream<Integer> stream = IntStream.rangeClosed(1, 10).boxed();
int[] array =  stream.mapToInt(x -> x).toArray();

Akış olmadan sadece IntStream kullanarak aynı şey

int[]array2 =  IntStream.rangeClosed(1, 10).toArray();

15

Java 8 akışını bu basit kod bloğunu kullanarak bir diziye dönüştürebilirsiniz:

 String[] myNewArray3 = myNewStream.toArray(String[]::new);

Ama şimdi daha fazla şey açıklayalım, önce üç değerle dolu bir dize listesi oluşturalım:

String[] stringList = {"Bachiri","Taoufiq","Abderrahman"};

Verilen Diziden bir akış oluşturun:

Stream<String> stringStream = Arrays.stream(stringList);

şimdi bu akışta bazı işlemler gerçekleştirebiliriz Ex:

Stream<String> myNewStream = stringStream.map(s -> s.toUpperCase());

ve son olarak şu yöntemleri kullanarak bir java 8 Array'a dönüştürün:

1-Klasik yöntem (Fonksiyonel arayüz)

IntFunction<String[]> intFunction = new IntFunction<String[]>() {
    @Override
    public String[] apply(int value) {
        return new String[value];
    }
};


String[] myNewArray = myNewStream.toArray(intFunction);

2 -Lambda ifadesi

 String[] myNewArray2 = myNewStream.toArray(value -> new String[value]);

3- Metot referansı

String[] myNewArray3 = myNewStream.toArray(String[]::new);

Yöntem referansı Açıklama:

Bir diğerine kesinlikle eşdeğer bir lambda ifadesi yazmanın başka bir yolu.


6

Metni, her değeri virgülle ayırarak dize dizisine dönüştürün ve her alanı kırpın, örneğin:

String[] stringArray = Arrays.stream(line.split(",")).map(String::trim).toArray(String[]::new);

4

Bir akışı diziye dönüştüren özel bir toplayıcı oluşturabilirsiniz.

public static <T> Collector<T, ?, T[]> toArray( IntFunction<T[]> converter )
{
    return Collectors.collectingAndThen( 
                  Collectors.toList(), 
                  list ->list.toArray( converter.apply( list.size() ) ) );
}

ve hızlı kullanım

List<String> input = Arrays.asList( ..... );

String[] result = input.stream().
         .collect( CustomCollectors.**toArray**( String[]::new ) );


Ben Collectors.groupingByöznitelik değeri başına nesnelerin dizilerine bazı öznitelik eşleştirmek böylece 2-arg geçmek için bir toplayıcı gerekiyordu . Bu cevap bana tam olarak bunu veriyor. Ayrıca @DidierL.
Ole VV

3

toArray(IntFunction<A[]> generator)Yöntemi kullanmak, bir Akışı aynı Akış türüne ait bir diziye dönüştürmenin (veya daha doğru bir şekilde toplamanın) çok zarif ve güvenli bir yoludur.

Döndürülen dizinin türü önemli değildir, ancak, sadece kullanan toArray()yöntem hem daha kolaydır ve daha kısa. Örneğin:

    Stream<Object> args = Stream.of(BigDecimal.ONE, "Two", 3);
    System.out.printf("%s, %s, %s!", args.toArray());

0
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

int[] arr=   stream.mapToInt(x->x.intValue()).toArray();

0
import java.util.List;
import java.util.stream.Stream;

class Main {

    public static void main(String[] args) {
        // Create a stream of strings from list of strings
        Stream<String> myStreamOfStrings = List.of("lala", "foo", "bar").stream();

        // Convert stream to array by using toArray method
        String[] myArrayOfStrings = myStreamOfStrings.toArray(String[]::new);

        // Print results
        for (String string : myArrayOfStrings) {
            System.out.println(string);
        }
    }
}

Çevrimiçi deneyin: https://repl.it/@SmaMa/Stream-to-array


Cevabınız ile kabul edilen cevap arasındaki fark nedir?
Uzun Nguyen

@LongNguyen Sadece snippet'i değil çevrimiçi tekrar senaryosunu da içeren tam bir örnektir.
Sma Ma

-1
     Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

     Integer[] integers = stream.toArray(it->new Integer[it]);

-2

Tüm yollar teknik olarak aynıdır, ancak Lambda kullanmak bazı kodları basitleştirecektir. Diyelim ki önce Dize ile bir Liste başlattık, buna kişi diyelim.

List<String> persons = new ArrayList<String>(){{add("a"); add("b"); add("c");}};
Stream<String> stream = persons.stream();

Şimdi aşağıdaki yollardan birini kullanabilirsiniz.

  1. Tanımlı boyutta yeni bir StringArray oluşturmak için Lambda Expresiion kullanma.

    String [] stringArray = stream.toArray (size-> yeni Dize [boyut]);

  2. Yöntem referansını doğrudan kullanma.

    String [] stringArray = stream.toArray (String [] :: new);

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.