แผนที่ () และ flatMap ()
map()
เพียงแค่ใช้ฟังก์ชั่นแลมบ์ดา param โดยที่ T คือองค์ประกอบและ R เป็นองค์ประกอบส่งคืนที่สร้างขึ้นโดยใช้ T ตอนท้ายเราจะมีสตรีมที่มีออบเจ็กต์ประเภทอาร์ตัวอย่างง่าย ๆ สามารถ:
Stream
.of(1,2,3,4,5)
.map(myInt -> "preFix_"+myInt)
.forEach(System.out::println);
มันใช้องค์ประกอบ 1 ถึง 5 ของชนิดInteger
ใช้แต่ละองค์ประกอบเพื่อสร้างองค์ประกอบใหม่จากชนิดที่String
มีค่า"prefix_"+integer_value
และพิมพ์ออกมา
flatMap()
มันมีประโยชน์ที่จะรู้ว่า flatMap () รับฟังก์ชั่นF<T, R>
ที่
T เป็นประเภทจากที่สตรีมสามารถสร้างขึ้นจาก / กับ มันสามารถเป็นรายการ (T.stream ()), อาเรย์ (Arrays.stream (someArray)) ฯลฯ อะไรก็ได้ที่สตรีมสามารถมี / หรือแบบฟอร์ม ในตัวอย่างด้านล่างแต่ละ dev มีหลายภาษาดังนั้น dev ภาษาเป็นรายการและจะใช้พารามิเตอร์แลมบ์ดา
R คือกระแสที่เกิดขึ้นซึ่งจะถูกสร้างโดยใช้ T เมื่อรู้ว่าเรามีอินสแตนซ์จำนวนมากของ T เราจะมีลำธารมากมายจาก R โดยธรรมชาติแล้วกระแสทั้งหมดจาก Type R จะรวมกันเป็นสตรีมเดียวจาก Type R .
ตัวอย่าง
ตัวอย่างของ Bachiri Taoufiq ดูคำตอบที่นี่ง่ายและเข้าใจง่าย เพียงเพื่อความชัดเจนสมมติว่าเรามีทีมนักพัฒนา:
dev_team = {dev_1,dev_2,dev_3}
กับนักพัฒนาซอฟต์แวร์แต่ละคนที่รู้หลายภาษา:
dev_1 = {lang_a,lang_b,lang_c},
dev_2 = {lang_d},
dev_2 = {lang_e,lang_f}
ใช้ Stream.map ()บน dev_team เพื่อรับภาษาของแต่ละ dev:
dev_team.map(dev -> dev.getLanguages())
จะให้โครงสร้างนี้กับคุณ:
{
{lang_a,lang_b,lang_c},
{lang_d},
{lang_e,lang_f}
}
List<List<Languages>> /Object[Languages[]]
ซึ่งเป็นพื้น ไม่ค่อยน่ารักเท่าไหร่และไม่เหมือน Java8 !!
เมื่อStream.flatMap()
คุณสามารถ 'แบน' สิ่งต่าง ๆ ออกมาตามโครงสร้างด้านบน
และเปลี่ยนเป็น{lang_a, lang_b, lang_c, lang_d, lang_e, lang_f}
ซึ่งโดยทั่วไปสามารถใช้เป็นList<Languages>/Language[]/etc
...
ดังนั้นในที่สุดรหัสของคุณจะมีความหมายมากกว่านี้:
dev_team
.stream() /* {dev_1,dev_2,dev_3} */
.map(dev -> dev.getLanguages()) /* {{lang_a,...,lang_c},{lang_d}{lang_e,lang_f}}} */
.flatMap(languages -> languages.stream()) /* {lang_a,...,lang_d, lang_e, lang_f} */
.doWhateverWithYourNewStreamHere();
หรือเพียงแค่:
dev_team
.stream() /* {dev_1,dev_2,dev_3} */
.flatMap(dev -> dev.getLanguages().stream()) /* {lang_a,...,lang_d, lang_e, lang_f} */
.doWhateverWithYourNewStreamHere();
เมื่อใดควรใช้ map () และใช้ flatMap () :
ใช้map()
เมื่อองค์ประกอบแต่ละประเภท T จากสตรีมของคุณควรจะถูกแมป / แปลงเป็นองค์ประกอบเดียวของประเภท R ผลที่ได้คือการแมปประเภท(องค์ประกอบเริ่มต้น 1 - องค์ประกอบเริ่ม 1> องค์ประกอบปลาย 1)และกระแสใหม่ขององค์ประกอบประเภท R ถูกส่งคืน
ใช้ flatMap()
เมื่อองค์ประกอบแต่ละประเภท T จากสตรีมของคุณควรจะแมป / เปลี่ยนเป็นชุดขององค์ประกอบของประเภท R ผลที่ได้คือการทำแผนที่ประเภท(องค์ประกอบเริ่มต้น 1 - องค์ประกอบสิ้นสุด> 1 คอลเลกชันเหล่านี้เป็นแล้วรวม (หรือบี้ ) เพื่อเป็นกระแสใหม่ขององค์ประกอบของประเภทอาร์นี้จะเป็นประโยชน์เช่นการเป็นตัวแทนของลูปซ้อนกัน
Pre Java 8:
List<Foo> myFoos = new ArrayList<Foo>();
for(Foo foo: myFoos){
for(Bar bar: foo.getMyBars()){
System.out.println(bar.getMyName());
}
}
โพสต์ Java 8
myFoos
.stream()
.flatMap(foo -> foo.getMyBars().stream())
.forEach(bar -> System.out.println(bar.getMyName()));
map :: Stream T -> (T -> R) -> Stream R
,flatMap :: Stream T -> (T -> Stream R) -> Stream R
.