จะแปลง Java 8 Stream เป็น Array ได้อย่างไร?


775

วิธีที่ง่ายที่สุด / สั้นที่สุดในการแปลง Java 8 Streamเป็นอาร์เรย์คืออะไร?


2
ฉันขอแนะนำให้คุณยกเลิกการย้อนกลับเนื่องจากคำถามนั้นสมบูรณ์มากขึ้นและแสดงว่าคุณได้ลองทำอะไรแล้ว
skiwi

2
@skiwi ขอบคุณ! แต่ฉันคิดว่ารหัสความพยายามไม่ได้เพิ่มข้อมูลเพิ่มเติมในคำถามและไม่มีใครตะโกน "แสดงความพยายามของคุณ" เลย =)

17
@skiwi: ถึงแม้ว่าฉันมักจะตะโกนใส่คำถามที่ทำที่บ้านของฉันแทนที่จะเป็นของฉันคำถามพิเศษนี้ดูเหมือนจะชัดเจนสำหรับฉันโดยไม่มีระเบียบเพิ่มเติม ขอให้เป็นระเบียบ
Honza Zidek

คุณสามารถหาคำตอบและคำแนะนำจำนวนมากได้ในเอกสารอย่างเป็นทางการของแพ็คเกจ: docs.oracle.com/javase/8/docs/api/java/util/stream/?hl=th
Christophe Roussy

คำตอบ:


1168

วิธีที่ง่ายที่สุดคือการใช้toArray(IntFunction<A[]> generator)วิธีที่มีการอ้างอิงตัวสร้างอาร์เรย์ นี้เป็นข้อเสนอแนะในเอกสาร API สำหรับวิธีการ

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

สิ่งที่มันคือหาวิธีที่ใช้ในจำนวนเต็ม (ขนาด) เป็นอาร์กิวเมนต์และส่งกลับString[]ซึ่งเป็นสิ่งที่ (หนึ่งใน overloads) new String[]ทำ

คุณสามารถเขียนของคุณเองIntFunction:

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

วัตถุประสงค์ของการIntFunction<A[]> generatorคือการแปลงจำนวนเต็มขนาดของอาร์เรย์ไปยังอาร์เรย์ใหม่

รหัสตัวอย่าง:

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

พิมพ์:

a
b
c

8
และนี่คือคำอธิบายว่าทำไมและวิธีการอ้างอิงตัวสร้างอาร์เรย์ทำงานอย่างไร: stackoverflow.com/questions/29447561/ …
jarek.jpa

"Zenexer ถูกต้องโซลูชันควรเป็น: stream.toArray (String [] :: new);" ... โอเค แต่เราควรเข้าใจว่าวิธีการอ้างอิงนั้นมีเหตุผลและมีประโยชน์เทียบเท่ากับtoArray(sz -> new String[sz])ดังนั้นฉันไม่แน่ใจว่าใครจะพูดได้ว่าสิ่งที่ควรจะเป็น
กอตต์

3
@scottb sz -> new String[sz]สร้างฟังก์ชันใหม่โดยที่ไม่มีการอ้างอิงคอนสตรัคเตอร์ ขึ้นอยู่กับว่าคุณให้ความสำคัญกับการเก็บขยะแบบไหน
WORMSS

3
@WORMSS มันไม่ได้ มัน (แบบคงที่!) สร้างprivate วิธีการใหม่ซึ่งไม่สามารถทำให้เกิดการสั่นสะเทือนและทั้งสองรุ่นจำเป็นต้องสร้างวัตถุใหม่ การอ้างอิงสร้างวัตถุที่ชี้ไปที่วิธีการเป้าหมายโดยตรง แลมบ์ดาสร้างวัตถุที่จุดที่สร้างขึ้นprivateอย่างใดอย่างหนึ่ง การอ้างอิงไปยังตัวสร้างควรยังคงทำงานได้ดีขึ้นเนื่องจากการขาดการอ้อมและการเพิ่มประสิทธิภาพ VM ที่ง่ายขึ้น แต่การปั่นไม่มีอะไรเกี่ยวข้องกับมัน
HTNW

2
@HTNW คุณถูกต้องขอโทษด้วย มันเป็นความพยายามของฉันในการแก้ไขข้อผิดพลาดที่ก่อให้เกิดการปั่นที่ก่อให้เกิดการปั่นป่วนครั้งแรกที่ฉันพยายามทำสิ่งนี้ดังนั้นฉันจึงติดอยู่ในหัวของฉันว่านี่เป็นอย่างไร (เกลียดเมื่อเกิดขึ้น)
WORMSS

41

หากคุณต้องการได้รับอาร์เรย์ของ ints ด้วยค่าแบบฟอร์ม 1 ถึง 10 จากสตรีมจะมี IntStream ตามที่คุณต้องการ

ที่นี่เราสร้าง Stream ด้วยวิธี Stream.of และแปลง Stream เป็น IntStream โดยใช้ mapToInt จากนั้นเราสามารถเรียกใช้เมธอด toArray ของ IntStream

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

นี่คือสิ่งเดียวกันโดยไม่มีสตรีมโดยใช้เพียง IntStream

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

15

คุณสามารถแปลงกระแสข้อมูล java 8 เป็นอาร์เรย์โดยใช้บล็อกโค้ดแบบง่ายนี้:

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

แต่ขออธิบายสิ่งต่าง ๆ ให้มากขึ้นก่อนอื่นมาสร้างรายการของสตริงที่เต็มไปด้วยค่าสามค่า:

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

สร้างกระแสจาก Array ที่กำหนด:

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

ตอนนี้เราสามารถทำการดำเนินการบางอย่างบนสตรีมนี้ Ex:

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

และในที่สุดก็แปลงเป็น java 8 Array โดยใช้วิธีเหล่านี้:

วิธีคลาสสิก 1 (อินเตอร์เฟซที่ใช้งานได้)

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


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

2- การแสดงออกแลมบ์ดา

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

3- การอ้างอิงวิธีการ

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

วิธีการอ้างอิงคำอธิบาย:

อีกวิธีหนึ่งในการเขียนแลมบ์ดานิพจน์ว่ามันเทียบเท่ากับอีกอย่างหนึ่ง


6

แปลงข้อความเป็นสตริงอาเรย์ที่คั่นแต่ละค่าด้วยเครื่องหมายจุลภาคและตัดทุกฟิลด์ตัวอย่างเช่น:

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

4

คุณสามารถสร้างตัวสะสมที่กำหนดเองที่แปลงกระแสเป็นอาร์เรย์

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

และใช้งานได้อย่างรวดเร็ว

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

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

5
ทำไมคุณจะใช้วิธีนี้แทนการStream.toArray (IntFunction) ?
Didier L

ฉันต้องการให้นักสะสมส่งต่อไปยัง 2-ARG Collectors.groupingByเพื่อที่ฉันจะได้แมปคุณลักษณะบางอย่างกับอาร์เรย์ของวัตถุต่อค่าแอตทริบิวต์ คำตอบนี้ให้ฉันอย่างนั้น ยัง @DidierL
Ole VV

3

การใช้toArray(IntFunction<A[]> generator)วิธีนี้เป็นวิธีที่สวยงามและปลอดภัยในการแปลง (หรือรวบรวมได้อย่างถูกต้องมากขึ้น) สตรีมเข้าสู่อาเรย์ประเภทเดียวกันของสตรีม

อย่างไรก็ตามถ้าประเภทของอาเรย์ที่คืนกลับมานั้นไม่สำคัญเพียงแค่ใช้toArray()เมธอดนั้นทั้งง่ายขึ้นและสั้นลง ตัวอย่างเช่น:

    Stream<Object> args = Stream.of(BigDecimal.ONE, "Two", 3);
    System.out.printf("%s, %s, %s!", args.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);
        }
    }
}

ลองใช้ออนไลน์: https://repl.it/@SmaMa/Stream-to-array


ความแตกต่างระหว่างคำตอบของคุณกับคำตอบที่ยอมรับคืออะไร?
Long Nguyen

@LongNguyen มันเป็นตัวอย่างที่สมบูรณ์รวมถึงสถานการณ์การเล่นซ้ำออนไลน์ไม่ใช่แค่ตัวอย่างเท่านั้น
Sma Ma


-2

คุณสามารถทำได้หลายวิธีวิธีการเหมือนกันทุกวิธี แต่การใช้แลมบ์ดาจะทำให้โค้ดบางอย่างง่ายขึ้น ให้บอกว่าเราเริ่มต้นรายการก่อนด้วย String เรียกมันว่าบุคคล

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

ตอนนี้คุณสามารถใช้วิธีใดวิธีหนึ่งต่อไปนี้

  1. การใช้ Lambda Expresiion เพื่อสร้าง StringArray ใหม่ด้วยขนาดที่กำหนด

    String [] stringArray = stream.toArray (size-> String ใหม่ [ขนาด]);

  2. ใช้วิธีการอ้างอิงโดยตรง

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.