ในโพสต์บล็อกนี้ เราจะอภิปรายฟีเจอร์ของ Java 8 Streams และให้ตัวอย่างโค้ดหลากหลายรูปแบบ
Java Streams นำ functional programming มาสู่ Java และรองรับตั้งแต่ Java 8 หากคุณมี Java เวอร์ชันเก่ากว่า ต้องอัปเกรดเป็น Java 8 เพื่อใช้ Java Streams
ทำไมต้องใช้ Java Streams?
ข้อดีบางอย่างของ Streams:
- Streams ทำให้คุณเป็น Java programmer ที่มีประสิทธิภาพมากขึ้น (จะเห็นได้ว่าเพียงไม่กี่บรรทัดโค้ด ทำได้เยอะมากกับ streams)
- ใช้ lambda expressions มาก ซึ่งเป็นฟังก์ชันแบบใช้ครั้งเดียวทิ้งได้
- ParallelStreams เปิดใช้งาน multi-threaded operations สำหรับข้อมูลขนาดใหญ่ได้อย่างง่ายดาย
Streams Pipeline
ในส่วนใหญ่ streams pipeline ประกอบด้วย:
- source (ที่ข้อมูลไหลออกมา)
- ตามด้วย intermediate operations ศูนย์หรือมากกว่า
- และ terminal operation หนึ่งตัว

Source จะสตรีม stream ของ elements
Stream ของ elements นี้สามารถ filtered, sorted, mapped หรือนำ operations อื่นๆ ไปประยุกต์กับแต่ละ element ได้
ท้ายสุด สามารถ collected, reduced หรือ terminal operations อื่นๆ ได้ แต่มี terminal operation เพียงตัวเดียวเท่านั้น
Stream Source
Stream source มาจาก collections, lists, sets, arrays ของ int, longs, double, strings ฯลฯ
Stream Operations
Stream operations เป็น intermediate หรือ terminal:
- Intermediate operations เช่น filter, map, sort คืนค่า stream เพื่อให้ chain intermediate operations หลายตัวได้
- Terminal operations รับ stream และคืนค่า void หรือ non-stream result เช่น reduction เช่น reduce items เป็น list
Intermediate Operations
- อนุญาต intermediate operations ศูนย์หรือมากกว่า
- ลำดับสำคัญ; สำหรับข้อมูลขนาดใหญ่: filter ก่อน แล้วค่อย sort หรือ map
- สำหรับข้อมูลขนาดใหญ่มาก ใช้ ParallelStream เพื่อเปิด multiple threads
Intermediate operations บางอย่างรวมถึง:
- anyMatch()
- distinct()
- filter()
- findFirst()
- flatmap()
- map()
- skip()
- sorted()
Terminal Operations
อนุญาต terminal operation เพียงตัวเดียว
- forEach ใช้ function เดียวกับทุก element เช่น print ทุก element
- collect เก็บ elements ทั้งหมดเข้า collection, list, หรือ array
- ตัวเลือกอื่นๆ ทุกรวม stream เป็น single summary element
ตัวอย่าง reduce functions:
- count()
- max()
- min()
- reduce()
ตัวอย่างโค้ด Java Streams
มาดู concepts ข้างต้นในโค้ดจริง
Integer Stream
ตัวอย่างแรกคือ integer stream เราสร้าง integer stream ด้วย class IntStream และฟังก์ชัน range ที่ให้ช่วง integers
forEach คือ terminal operation ของเรา สำหรับแต่ละ item เราแค่ print ออกมา
import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams { public static void main(String[] args) throws IOException { IntStream .range(1, 10) .forEach(System.out::print); System.out.println(); } }
Output:
123456789
Integer Stream with Skip
ตัวอย่างที่สองใช้ integer stream แต่เพิ่ม skip() ในกรณีนี้ เราจะข้าม 5 elements แรกของ stream
จะพิมพ์แค่ elements 6 ถึง 9 เรายังใช้ lambda expression เรียบง่ายพิมพ์ item
import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams { public static void main(String[] args) throws IOException { IntStream .range(1, 10) .skip(5) .forEach(x -> System.out.println(x)); System.out.println(); } }
Output:
6 7 8 9
Integer Stream with Sum
ตัวอย่างที่สาม เราใช้ IntStream สร้าง stream of objects อีกครั้ง แต่วางไว้ใน println() statement เป็น parameter
สิ่งที่จะพิมพ์คือ sum จาก range 1 ถึง 5 คือ 1 2 3 & 4 จะพิมพ์แค่ผลรวมของตัวเลขเหล่านั้น:
import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams { public static void main(String[] args) throws IOException { System.out.println( IntStream .range(1, 5) .sum()); System.out.println(); } }
Output:
10
Stream.of
ตัวอย่างถัดไปใช้ฟังก์ชัน Stream.of ซึ่งสะดวกมาก เพราะ stream integers, floating point values, strings หรือแม้แต่ objects ได้
ในตัวอย่างนี้ เราแค่ sort ตามอักษร แล้วหา item แรกด้วย findFirst() แล้วพิมพ์ item แรกใน list
import java.io.IOException; import java.util.stream.Stream; public class JavaStreams { public static void main(String[] args) throws IOException { Stream.of("Ava", "Aneri", "Alberto") .sorted() .findFirst() .ifPresent(System.out::println); } }
Output
Alberto
Stream from Array, sort, filter and print
ตัวอย่างต่อไป เราจะ stream จาก array แล้ว sort, filter และ print
ที่นี่ เราจะ filter เฉพาะ items ที่ขึ้นต้นด้วย s
เราใช้ lambda expression ที่รับ X ซึ่งคือแต่ละชื่อ แล้วเช็คว่าตัวไหนขึ้นต้นด้วยตัวอักษร s และส่งต่อไป
จากนั้น sort แล้ว forEach item ที่ผ่าน sort เราพิมพ์ออกมา
import java.io.IOException; import java.util.Arrays; public class JavaStreams { public static void main(String[] args) throws IOException { String[] names = {"Al", "Ankit", "Kushal", "Brent", "Sarika", "amanda", "Hans", "Shivika", "Sarah"}; Arrays.stream(names) .filter(x -> x.startsWith("S")) .sorted() .forEach(System.out::println); } }
Output:
Sarah Sarika Shivika
Average of Integer Array
มาดูวิธีหาค่าเฉลี่ยของกำลังสองของ int array
ที่นี่ เราใช้ Arrays.stream() สตรีม integers แล้วใช้ map() map แต่ละ integer ไปยังกำลังสองของมัน
import java.util.Arrays; public class JavaStreams { public static void main(String[] args) { Arrays.stream(new int[] {2, 4, 6, 8, 10}) .map(x -> x * x) .average() .ifPresent(System.out::println); } }
Output:
44.0
สังเกตว่าพิมพ์เป็น double ไม่ใช่ integer
Stream from List, filter and print
ในตัวอย่างนี้ เราจะ stream จาก list filter items แล้ว print
สังเกตว่าในฟังก์ชัน map() เราจะแปลงชื่อทั้งหมดเป็น lowercase
import java.util.Arrays; import java.util.List; public class JavaStreams { public static void main(String[] args) { List people = Arrays.asList("Al", "Ankit", "Brent", "Sarika", "amanda", "Hans", "Shivika", "Sarah"); people .stream() .map(String::toLowerCase) .filter(x -> x.startsWith("a")) .forEach(System.out::println); } }
Output:
al ankit amanda
เห็นว่ามี 3 ชื่อขึ้นต้นด้วย a และเป็น lowercase ทั้งหมด
Stream rows from text file, sort, filter, and print
ตัวอย่างต่อไป เราจะ stream rows จาก text file sort, filter และ print
สมมติเรามีไฟล์ bands.txt เนื้อหา:
Rolling Stones Lady Gaga Jackson Browne Maroon 5 Arijit Singh Elton John John Mayer CCR Eagles Pink Aerosmith Adele Taylor Swift
เราจะใช้ Files.lines() สร้าง stream ให้ได้ stream ของ string สำหรับแต่ละบรรทัดของไฟล์
เมื่อได้ stream เราจะ sort และ filter เฉพาะ items ที่ยาวกว่า 13 ตัวอักษร แล้วพิมพ์ items ที่เหลือ
สุดท้าย ต้องปิดไฟล์ ดังนั้น bands.close
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.stream.Stream; public class JavaStreams { public static void main(String[] args) throws IOException { Stream bands = Files.lines(Paths.get("bands.txt")); bands .sorted() .filter(x -> x.length() > 13) .forEach(System.out::println); bands.close(); } }
Output:
Jackson Browne Rolling Stones
ได้ 2 bands ที่มีมากกว่า 13 ตัวอักษร
Stream rows from text file and save to List
ตัวอย่างนี้ใช้ text file เดียวกับข้างต้น
เราอยาก filter items ที่มีตัวอักษร jit ใช้ x.contains() ซึ่งเป็น string function
ใช้ .collect() รวบรวม items ที่มี jit เข้า list
เมื่อได้ list ใช้ forEach operator พิมพ์ items
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; public class JavaStreams { public static void main(String[] args) throws IOException { List bands2 = Files.lines(Paths.get("bands.txt")) .filter(x -> x.contains("jit")) .collect(Collectors.toList()); bands2.forEach(x -> System.out.println(x)); } }
Output:
Arijit Singh
Stream rows from CSV file and count
ตัวอย่างนี้ stream rows จาก CSV file และนับ good rows
สมมติมีไฟล์ data.txt เนื้อหา:
A,12,3.7 B,17,2.8 C,14,1.9 D,23,2.7 E F,18,3.4
ที่นี่ row E ไม่มีข้อมูล จึง exclude ออกจาก stream
ในโค้ดต่อไป เราอ่านแต่ละ row แล้ว split ที่ comma เป็น array แต่ละ row จะกลายเป็น array of items
จากนั้น apply filter กรอง rows ที่ไม่มี 3 items
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.stream.Stream; public class JavaStreams { public static void main(String[] args) throws IOException { Stream rows1 = Files.lines(Paths.get("data.txt")); int rowCount = (int)rows1 .map(x -> x.split(",")) .filter(x -> x.length == 3) .count(); System.out.println(rowCount + " rows."); rows1.close(); } }
Output:
5 rows
Reduction - sum
ตัวอย่างนี้แสดงวิธีใช้ reduction เราจะ reduce เป็น sum ที่นี่ เรามี double stream ด้วย Stream.of() กำหนด doubles 3 ตัวใน 3 arguments แล้วใช้ reduce function
import java.util.stream.Stream; public class JavaStreams { public static void main(String[] args) { double total = Stream.of(7.3, 1.5, 4.8) .reduce(0.0, (Double a, Double b) -> a + b); System.out.println("Total = " + total); } }
Output:
13.600000000000001