เมื่อใดก็ตามที่ฉันต้องการสร้างสตรีมจากอาร์เรย์ฉันจะทำ
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 ด้วยองค์ประกอบเดียวLongStream
Stream.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