Java 8 สตรีมและการใช้งานบนอาร์เรย์


197

ฉันเพิ่งค้นพบความสามารถของสตรีม Java 8 ใหม่ มาจาก Python ฉันสงสัยว่าตอนนี้มีวิธีที่ประณีตในการดำเนินการกับอาเรย์เช่นการหาผลรวมการคูณสองอาร์เรย์ในรูปแบบ "one pythonic" หรือไม่?

ขอบคุณ

คำตอบ:


294

มีวิธีการใหม่ที่เพิ่มเข้าไปในjava.util.Arraysการแปลงอาร์เรย์เป็นสตรีม Java 8 ซึ่งสามารถใช้สำหรับการสรุป ฯลฯ

int sum =  Arrays.stream(myIntArray)
                 .sum();

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

//in this example a[] and b[] are same length
int[] a = ...
int[] b = ...

int[] result = new int[a.length];

IntStream.range(0, a.length)
         .forEach(i -> result[i] = a[i] * b[i]);

แก้ไข

Commenter @Holgerชี้ให้เห็นว่าคุณสามารถใช้mapวิธีการแทนวิธีforEachนี้:

int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray();

13
int[] result=IntStream.range(0, a.length).map( i->a[i]* b[i]).toArray();
Holger

2
@ Holger ใช่ว่าจะใช้งานได้เช่นกัน แม้ว่าคุณอาจต้องการใช้mapToIntเพื่อหลีกเลี่ยงการชกมวย
dkatzel

จำนวนสุดท้ายจะเป็นการจำลองแบบซิปซึ่งคุณต้องจัดสรรล่วงหน้าพื้นที่เก็บข้อมูลสำหรับผลลัพธ์ ฉันสงสัยว่าทำไมไม่มีซิปในห้องสมุด Streams
Reb.Cabin

ตามคำตอบ SO นี้ซิปอยู่ในรุ่นเบต้าก่อนหน้าของ Java 8 แล้วนำออกมา โชคดีที่โปสเตอร์มีต้นกำเนิดและเป็นคำตอบ ฉันใช้รหัสหลายครั้งและดูเหมือนว่าจะทำงานได้ดีมาก
sparc_spread

@dkatzel - เนื่องจากเป็น IntStream อยู่แล้ว "map" จึงใช้ IntUnaryOperator ดังนั้นจึงไม่มีการชกมวย
M. Justin

58

คุณสามารถเปลี่ยนอาร์เรย์เป็นสตรีมได้โดยใช้Arrays.stream():

int[] ns = new int[] {1,2,3,4,5};
Arrays.stream(ns);

เมื่อคุณได้รับกระแสข้อมูลคุณสามารถใช้วิธีการใด ๆ ที่อธิบายไว้ในเอกสารประกอบเช่นsum()หรืออะไรก็ตาม คุณสามารถmapหรือfilterชอบใน Python โดยเรียกวิธีการสตรีมที่เกี่ยวข้องด้วยฟังก์ชั่น Lambda:

Arrays.stream(ns).map(n -> n * 2);
Arrays.stream(ns).filter(n -> n % 4 == 0);

เมื่อคุณปรับเปลี่ยนสตรีมของคุณเสร็จแล้วคุณสามารถโทรtoArray()เพื่อแปลงกลับเป็นอาร์เรย์เพื่อใช้ที่อื่น:

int[] ns = new int[] {1,2,3,4,5};
int[] ms = Arrays.stream(ns).map(n -> n * 2).filter(n -> n % 4 == 0).toArray();

9

ระวังถ้าคุณต้องรับมือกับจำนวนมาก

int[] arr = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE};
long sum = Arrays.stream(arr).sum(); // Wrong: sum == 0

2 * Integer.MIN_VALUEผลรวมข้างต้นไม่ คุณต้องทำในกรณีนี้

long sum = Arrays.stream(arr).mapToLong(Long::valueOf).sum(); // Correct

3

โปรดทราบว่า Arrays.stream (arr) สร้าง LongStream (หรือ IntStream, ... ) แทน Stream เพื่อไม่ให้ฟังก์ชั่นแผนที่ใช้ในการปรับเปลี่ยนประเภท นี่คือเหตุผลที่ฟังก์ชัน. mapToLong, mapToObject, ...

ลองดูเหตุผลว่าทำไมถึงไม่ -i-map-integers-to-strings-when-streaming-from-an-array

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