ฉันต้องการ ฟังก์ชั่นแผนที่ มีบางอย่างเช่นนี้ใน Java อยู่แล้ว?
(สำหรับผู้ที่สงสัยว่า: แน่นอนฉันรู้วิธีการใช้ฟังก์ชั่นเล็กน้อยนี้เอง ... )
ฉันต้องการ ฟังก์ชั่นแผนที่ มีบางอย่างเช่นนี้ใน Java อยู่แล้ว?
(สำหรับผู้ที่สงสัยว่า: แน่นอนฉันรู้วิธีการใช้ฟังก์ชั่นเล็กน้อยนี้เอง ... )
คำตอบ:
ไม่มีความคิดของฟังก์ชั่นใน JDK เป็นของ java 6
Guavaมีส่วนต่อประสานฟังก์ชั่นและ
วิธีการใช้งานที่คุณต้องการ
Collections2.transform(Collection<E>, Function<E,E2>)
ตัวอย่าง:
// example, converts a collection of integers to their
// hexadecimal string representations
final Collection<Integer> input = Arrays.asList(10, 20, 30, 40, 50);
final Collection<String> output =
Collections2.transform(input, new Function<Integer, String>(){
@Override
public String apply(final Integer input){
return Integer.toHexString(input.intValue());
}
});
System.out.println(output);
เอาท์พุท:
[a, 14, 1e, 28, 32]
ทุกวันนี้ด้วย Java 8 มีฟังก์ชั่นแผนที่อยู่จริงดังนั้นฉันอาจจะเขียนโค้ดด้วยวิธีที่กระชับกว่านี้:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
ตั้งแต่ Java 8 มีตัวเลือกมาตรฐานให้ทำใน JDK:
Collection<E> in = ...
Object[] mapped = in.stream().map(e -> doMap(e)).toArray();
// or
List<E> mapped = in.stream().map(e -> doMap(e)).collect(Collectors.toList());
ดู java.util.Collection.stream()
java.util.stream.Collectors.toList()
และ
toList()
ตกลงเกี่ยวกับ เปลี่ยนเป็นประเภทอื่น:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
ถูกแทนที่ด้วยเพียงdoMap
?
foo::doMap
Foo::doMap
มีไลบรารีที่ยอดเยี่ยมที่เรียกว่าFunctional Javaซึ่งจัดการหลายสิ่งที่คุณต้องการให้ Java มี แต่มันไม่มี จากนั้นอีกครั้งมี Scala ภาษาที่ยอดเยี่ยมนี้ซึ่งทำทุกสิ่งที่ Java ควรทำ แต่ไม่ได้ในขณะที่ยังเข้ากันได้กับสิ่งที่เขียนขึ้นสำหรับ JVM
a.map({int i => i + 42});
พวกเขาขยายคอมไพเลอร์หรือไม่? หรือเพิ่มโปรเซสเซอร์ล่วงหน้า?
ระวังด้วยCollections2.transform()
จากฝรั่ง ความได้เปรียบที่ยิ่งใหญ่ที่สุดของวิธีการนั้นก็เป็นอันตรายที่ยิ่งใหญ่เช่นกัน
ดูเอกสารของLists.transform()
ซึ่งฉันเชื่อว่าใช้กับCollections2.transform()
:
ฟังก์ชั่นนี้ใช้งานได้อย่างเกียจคร้านเมื่อถูกเรียกใช้ นี่เป็นสิ่งจำเป็นสำหรับรายการที่ส่งคืนเพื่อเป็นมุมมอง แต่หมายความว่าฟังก์ชันจะถูกนำไปใช้หลายครั้งสำหรับการดำเนินการจำนวนมากเช่น List.contain (java.lang.Object) และ List.hashCode () เพื่อให้ทำงานได้ดีฟังก์ชั่นควรเร็ว เพื่อหลีกเลี่ยงการประเมินที่ขี้เกียจเมื่อรายการที่ส่งคืนไม่จำเป็นต้องเป็นมุมมองให้คัดลอกรายการที่ส่งคืนไปยังรายการใหม่ที่คุณเลือก
นอกจากนี้ในเอกสารประกอบของCollections2.transform()
พวกเขาพูดถึงคุณได้รับมุมมองสดการเปลี่ยนแปลงในรายการแหล่งที่มามีผลต่อรายการเปลี่ยนแปลง พฤติกรรมประเภทนี้อาจนำไปสู่ปัญหาที่ยากต่อการติดตามหากนักพัฒนาซอฟต์แวร์ไม่เข้าใจวิธีการทำงาน
หากคุณต้องการ "แผนที่" แบบคลาสสิกยิ่งขึ้นนั่นจะทำงานเพียงครั้งเดียวเท่านั้นคุณก็จะดีขึ้นด้วยFluentIterable
เช่นกันจาก Guava ซึ่งมีการใช้งานที่ง่ายกว่ามาก นี่คือตัวอย่างของ google มัน:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
นี่คือวิธีการแผนที่ จะใช้ฟังก์ชั่นเดียวกัน <> "เรียกกลับ" Collections.transform()
เป็น รายการที่คุณได้รับกลับมาเป็นแบบอ่านอย่างเดียว แต่ใช้copyInto()
เพื่อรับรายการอ่าน - เขียน
มิฉะนั้นแน่นอนเมื่อ java8 ออกมาพร้อมกับ lambdas สิ่งนี้จะล้าสมัย
นี่เป็นอีกหนึ่งฟังก์ชั่น lib ที่คุณสามารถใช้แผนที่ได้: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
แม้ว่าจะเป็นคำถามเก่าที่ฉันต้องการแสดงวิธีแก้ไขปัญหาอื่น:
เพียงกำหนดการทำงานของคุณเองโดยใช้ java generics และ java 8 stream:
public static <S, T> List<T> map(Collection<S> collection, Function<S, T> mapFunction) {
return collection.stream().map(mapFunction).collect(Collectors.toList());
}
คุณสามารถเขียนโค้ดดังนี้:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);