Java11のジェネリックコレクションにマップする[複製]

Nov 28 2020

私は、コレクションにマップするためのジェネリック関数(おそらくジェネリックを使用しない)を作成する方法を見つけようとしてきました。

関数AからBがあるとしましょう。aを取り、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>ためのサプライヤを取得する方法がわからないため、でタイプエラーが発生します。

編集:この関数を一般的な方法で使用できるようにしたいと思います。Setを渡すとSetが返されますが、Listを渡すとListが返されます。これを行うことさえ可能ですか?

回答

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]