เมื่อใดก็ตามที่ฉันต้องการสร้างสตรีมจากอาร์เรย์ฉันจะทำ
String[] array = {"x1", "x2"};
Arrays.asList(array).stream();
มีวิธีโดยตรงในการสร้างสตรีมจากอาร์เรย์หรือไม่?
เมื่อใดก็ตามที่ฉันต้องการสร้างสตรีมจากอาร์เรย์ฉันจะทำ
String[] array = {"x1", "x2"};
Arrays.asList(array).stream();
มีวิธีโดยตรงในการสร้างสตรีมจากอาร์เรย์หรือไม่?
คำตอบ:
คุณสามารถใช้ Arrays.stream เช่น
Arrays.stream(array);
คุณยังสามารถใช้Stream.ofตามที่ @fge กล่าวไว้ได้ซึ่งมีลักษณะดังนี้
public static<T> Stream<T> of(T... values) {
return Arrays.stream(values);
}
แต่ทราบStream.of(intArray)จะกลับมาStream<int[]>ในขณะที่Arrays.stream(intArr)จะกลับมาให้คุณผ่านอาร์เรย์ของพิมพ์IntStream int[]ดังนั้นโดยสรุปสำหรับประเภทดั้งเดิมคุณสามารถสังเกตความแตกต่างระหว่าง 2 วิธีเช่น
int[] arr = {1, 2};
Stream<int[]> arr1 = Stream.of(arr);
IntStream stream2 = Arrays.stream(arr);
เมื่อคุณส่งอาร์เรย์ดั้งเดิมไปยังArrays.streamโค้ดต่อไปนี้จะถูกเรียกใช้
public static IntStream stream(int[] array) {
return stream(array, 0, array.length);
}
และเมื่อคุณส่งอาร์เรย์ดั้งเดิมไปStream.ofยังรหัสต่อไปนี้จะถูกเรียกใช้
public static<T> Stream<T> of(T t) {
return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
}
ดังนั้นคุณจะได้รับผลลัพธ์ที่แตกต่างกัน
อัปเดต : ตามที่กล่าวไว้โดยความคิดเห็นของStuart Marksการโอเวอร์โหลดของช่วงย่อยArrays.streamเป็นที่นิยมในการใช้Stream.of(array).skip(n).limit(m)เนื่องจากผลลัพธ์ก่อนหน้านี้ในสตรีม SIZED ในขณะที่หลังไม่ได้ เหตุผลก็คือlimit(m)ไม่ทราบว่าขนาดคือ m หรือน้อยกว่า m ในขณะที่Arrays.streamตรวจสอบช่วงและทราบขนาดที่แน่นอนของสตรีมคุณสามารถอ่านซอร์สโค้ดสำหรับการใช้งานสตรีมที่ส่งคืนได้Arrays.stream(array,start,end) ที่นี่ในขณะที่การใช้งานสตรีมกลับมาStream.of(array).skip().limit()คือ ภายในวิธีนี้
Stream.ofอาจทำให้คุณประหลาดใจ (เช่นเมื่อคุณโทรArrays.asListด้วยอาร์เรย์ดั้งเดิมและผู้คนคาดหวังว่าจะได้รับการตอบList<Integer>กลับ) :-)
Arrays.streamรองรับการสตรีมช่วงของอาร์เรย์ซึ่งIntStream.ofไม่ได้ ในทางตรงกันข้ามStream.ofเป็นทางเลือกที่ดีกว่าถ้าคุณต้องการStream<int[]>ขนาด1...
Arrays.streamนั้นดีกว่าที่จะใช้Stream.of(array).skip(n).limit(m)เนื่องจากผลลัพธ์เดิมในสตรีม SIZED ในขณะที่หลังไม่ได้ เหตุผลก็คือlimit(m)ไม่ทราบว่ามีขนาดmหรือน้อยกว่าmในขณะที่Arrays.streamตรวจสอบช่วงและทราบขนาดที่แน่นอนของสตรีม
Arrays.stream(array,start,end)ส่งคืนการStreamดำเนินการที่มีอยู่ที่นี่ในขณะที่Stream.of(array).skip().limit()ส่งกลับการStreamดำเนินการที่อยู่ในวิธีนี้
ทางเลือกในการแก้ปัญหาของ @ sol4me:
Stream.of(theArray)
จากความแตกต่างระหว่างสิ่งนี้และArrays.stream(): จะสร้างความแตกต่างหากอาร์เรย์ของคุณเป็นประเภทดั้งเดิม ตัวอย่างเช่นหากคุณทำ:
Arrays.stream(someArray)
ที่someArrayเป็นก็จะกลับมาเป็นlong[] ในทางกลับกันจะส่งคืน a ด้วยองค์ประกอบเดียวLongStreamStream.of()Stream<long[]>
Arrays.stream()ใช้ได้เช่นกัน
*Stream.of()เมื่อคุณArrays.stream()จัดการกับอาร์เรย์ดั้งเดิม และสำหรับอาร์เรย์ที่ไม่ใช่วัตถุจริงนี่คือ Java ซึ่งเป็นเช่นนี้มาตั้งแต่ 1.0 ดังนั้นจัดการกับมัน การครุ่นคิดเรื่องนี้ไม่ช่วยอะไรเลย
Arrays.stream()ไม่สะดวกผมถือว่าสะดวก พูดพอแล้ว.
*Stream.of()สะดวกกว่าที่จะเข้าใจผิด เพราะมันเป็นเรื่องของการตั้งค่า ฉันชอบArrays.stream()สำหรับกรณีเช่นนี้ซึ่งทำให้ผิดเป็นกฎทั่วไปที่Stream.of()สะดวกกว่า (พีชคณิต Peano)
Stream.of("foo", "bar", "baz")
หรือถ้าคุณมีอาร์เรย์อยู่แล้วคุณสามารถทำได้เช่นกัน
Stream.of(array)
สำหรับประเภทดั้งเดิมใช้IntStream.ofหรือLongStream.ofอื่น ๆ
int[]สามารถส่งผ่านไปยังวิธีการยอมรับ varargs ทำไมไม่Stream.of(intArray)สร้าง a Stream<Integer>แทนStream<int[]>? นอกจากนี้ยังมีเหตุผลทางเทคนิคใด ๆ ว่าทำไมจึงมีคลาส Stream พิเศษสำหรับดั้งเดิม?
int[]ไม่เหมือนกับอาร์เรย์อื่น ๆ ไม่ใช่คลาสย่อยของObject[]แต่เป็นคลาสย่อยของObject. ดังนั้นเมื่อคุณผ่านไปStream.ofก็นำมาเป็นพารามิเตอร์และคุณได้รับกระแสของObject int[]นั่นเป็นหนึ่งในเหตุผลที่ต้องมีคลาสพิเศษสำหรับดั้งเดิม - หากคุณไม่ได้สร้างสตรีมจากอาร์เรย์ดั้งเดิมจะค่อนข้างเจ็บปวด อีกเหตุผลหนึ่งคือการเรียนเฉพาะทางมีประสิทธิภาพมากกว่าเนื่องจากไม่จำเป็นต้องเสียObjectค่าใช้จ่ายจากการชกมวย (แปลงintเป็นIntegerเพื่อให้ดูเหมือนวัตถุทั่วไป)
int[]เป็นObjectก็จะตรงกับวิธีการมากเกินไปและด้วยเหตุนี้มันกลับof(T t) Stream<int[]>ดังนั้นในทางทฤษฎีถ้าไม่มีวิธีนี้เราจะได้รับStream<Integer>ผลตอบแทน? หรืออาจทำให้เกิดข้อผิดพลาดในการคอมไพล์เนื่องจากไม่พบวิธีการจับคู่? เช่นint[]ไม่สามารถถือว่าเป็นT...
Stream<Integer>เพราะStream.of(t ... T) ยังคงจับคู่แบบเดิม
คุณสามารถทำได้ด้วยวิธีระดับต่ำซึ่งมีตัวเลือกคู่ขนาน:
/**
* Creates a new sequential or parallel {@code Stream} from a
* {@code Spliterator}.
*
* <p>The spliterator is only traversed, split, or queried for estimated
* size after the terminal operation of the stream pipeline commences.
*
* @param <T> the type of stream elements
* @param spliterator a {@code Spliterator} describing the stream elements
* @param parallel if {@code true} then the returned stream is a parallel
* stream; if {@code false} the returned stream is a sequential
* stream.
* @return a new sequential or parallel {@code Stream}
*
* <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel)
*/
StreamSupport.stream(Arrays.spliterator(array, 0, array.length), true)
คุณสามารถใช้ Arrays.stream:
Arrays.stream (อาร์เรย์);
เพื่อให้แน่ใจว่านี้เป็นชนิดที่การกลับมาของไอน้ำขึ้นอยู่กับประเภทการป้อนข้อมูลอาร์เรย์ของคุณหากString []แล้วกลับStream<String>ถ้าint []ผลตอบแทนแล้วIntStream
เมื่อคุณรู้จักอาร์เรย์ประเภทอินพุตแล้วคุณควรใช้อาร์เรย์เฉพาะเช่นสำหรับประเภทอินพุต int[]
IntStream.of (อาร์เรย์);
ส่งคืน Intstream
ในตัวอย่างแรก Java ใช้วิธีoverloadingการค้นหาวิธีการเฉพาะตามประเภทอินพุตในขณะที่ในวินาทีที่คุณรู้จักประเภทอินพุตและเรียกวิธีการเฉพาะแล้ว
ไม่ค่อยเห็น แต่นี่เป็นวิธีที่ตรงที่สุด
Stream.Builder<String> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
builder.add( array[i] );
Stream<String> stream = builder.build();
Arrays.streamมีกรณีที่โอเวอร์โหลดทั้งหมดสำหรับอาร์เรย์ดั้งเดิม IEStream.of(new int[]{1,2,3})จะให้คุณStream<int[]>ในขณะที่Arrays.streamจะให้คุณกลับIntStreamซึ่งอาจเป็นสิ่งที่คุณต้องการ ดังนั้น +1