Zuordnung über generische Sammlung in Java 11 [Duplikat]

Nov 28 2020

Ich habe versucht, eine Möglichkeit zu finden, eine generische Funktion zu schreiben - möglicherweise ohne Generika -, um eine Sammlung abzubilden.

Angenommen, ich habe eine Funktion von A bis B. Ich möchte eine Funktion schreiben, die a nimmt Collection<A>und a zurückgibt Collection<B>. HINWEIS: A und B sind keine Generika, sondern nur eine Möglichkeit, ein allgemeines Muster auszudrücken.

Was ich bisher habe ist

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

}

Ich erhalte jedoch einen Tippfehler in der .collect, weil ich natürlich möchte, dass die neue Sammlung ist, Collection<Point>aber ich bin nicht sicher, wie ich einen Lieferanten dafür bekommen kann?

Bearbeiten: Ich möchte diese Funktion generisch nutzen können: Wenn ich ein Set übergebe, bekomme ich ein Set zurück, aber wenn ich es als Liste übergebe, bekomme ich eine Liste zurück. ist das überhaupt möglich?

Antworten

3 dreamcrash Nov 28 2020 at 03:32

Die beste Option ist, nicht zu kompliziert zu werden und einfach Folgendes zu tun:

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

eine konkrete Implementierung der Schnittstelle Rückkehr Collection( zB Collectors.toList() ) , während von außen die Details der Implementierung versteckt, ( dh mit Collectionin der Methodensignatur).

Sie können Ihre Methode jedoch allgemeiner gestalten, indem Sie ihr als Supplierkonkrete Implementierung der Schnittstelle übergeben Collection, die sie zurückgeben soll, nämlich

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

Auf diese Weise können Sie die konkrete CollectionImplementierung übergeben, die zurückgegeben wird, zum Beispiel:

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

Ersetzen Sie die Anweisung Collectors.toCollection(() -> points)durch Collectors.toList().

Demo:

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());    
    }
}

Ausgabe:

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