แมปทับคอลเลคชันทั่วไปใน Java 11 [ซ้ำ]

Nov 28 2020

ฉันพยายามหาวิธีเขียนฟังก์ชันทั่วไป - อาจไม่ได้ใช้ generics - เพื่อแมปบนคอลเล็กชัน

สมมติว่าผมมีฟังก์ชั่น A ไป B ผมอยากจะเขียนฟังก์ชั่นที่ใช้เวลาเป็นและผลตอบแทนCollection<A> Collection<B>โปรดทราบว่า A และ B ไม่ใช่ยาสามัญ แต่เป็นเพียงวิธีแสดงรูปแบบทั่วไป

สิ่งที่ฉันมีจนถึงตอนนี้คือ

public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
    return points.stream()
            .map(Utils::point2dToPoint)
            .collect(Collectors.toCollection(() -> points));

}

อย่างไรก็ตามฉันได้รับข้อผิดพลาดประเภท.collectเนื่องจากเห็นได้ชัดว่าฉันต้องการให้คอลเลกชันใหม่เป็นCollection<Point>แต่ฉันไม่แน่ใจว่าจะรับ Supplier ได้อย่างไร?

แก้ไข: ฉันต้องการใช้ฟังก์ชันนี้ในลักษณะทั่วไป: ถ้าฉันส่งชุดไปฉันจะได้รับชุดกลับมา แต่ถ้าฉันส่งผ่านรายการฉันจะได้รับรายการตอบแทน เป็นไปได้ไหมที่จะทำเช่นนี้?

คำตอบ

3 dreamcrash Nov 28 2020 at 03:32

ทางเลือกที่ดีที่สุดคืออย่าทำซ้ำซ้อนและทำดังนี้

public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
    return points.stream()
            .map(Utils::point2dToPoint)
            .collect(Collectors.toList());
}

ส่งคืนการใช้งานอินเทอร์เฟซที่เป็นรูปธรรมCollection( เช่น Collectors.toList() ) ในขณะที่ซ่อนรายละเอียดการใช้งานจากภายนอก ( กล่าวคือมีCollectionในลายเซ็นของวิธีการ)

อย่างไรก็ตามคุณสามารถทำให้วิธีการของคุณเป็นแบบทั่วไปมากขึ้นโดยส่งผ่านไปยังSupplier- ซึ่งเป็นการนำอินเทอร์เฟซที่Collectionคุณต้องการให้กลับมาใช้อย่างเป็นรูปธรรมนั่นคือ

 public static Collection<Point> points2dToPoints(Collection<Point2D> points, Supplier<Collection<Point>> aNew) {
        return points.stream()
                .map(Utils::point2dToPoint)
                .collect(toCollection(aNew));

ด้วยวิธีนี้คุณสามารถส่งผ่านการCollectionใช้งานที่เป็นรูปธรรมซึ่งจะถูกส่งคืนตัวอย่างเช่น:

points2dToPoints(.., ArrayList::new);
points2dToPoints(.., TreeSet::new);
2 LiveandLetLive Nov 28 2020 at 03:31

แทนที่คำสั่งCollectors.toCollection(() -> points)ด้วยCollectors.toList().

การสาธิต:

import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

class Car {
    String name;

    public Car(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Car [name=" + name + "]";
    }
}

class Book {
    Car car;

    public Book(Car car) {
        this.car = car;
    }

    public Car getCar() {
        return car;
    }
}

public class Main {
    public static void main(String[] args) {
        // Test
        Collection<Car> list = points2dToPoints(
                List.of(new Book(new Car("Toyota")), new Book(new Car("Ford")), new Book(new Car("Suzuki"))));

        list.forEach(System.out::println);
    }

    public static Collection<Car> points2dToPoints(Collection<Book> points) {
        return points.stream().map(Book::getCar).collect(Collectors.toList());    
    }
}

เอาท์พุต:

Car [name=Toyota]
Car [name=Ford]
Car [name=Suzuki]