Memetakan koleksi umum di Java 11 [duplikat]
Saya telah mencoba menemukan cara untuk menulis fungsi generik - mungkin tidak menggunakan generik - untuk memetakan koleksi.
Katakanlah saya memiliki fungsi A ke B, saya ingin menulis fungsi yang mengambil a Collection<A>
dan mengembalikan a Collection<B>
. Perhatikan bahwa A dan B bukanlah generik, hanya cara untuk mengekspresikan pola umum.
Apa yang saya miliki sejauh ini
public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(Collectors.toCollection(() -> points));
}
Namun, saya mendapatkan kesalahan tipe di .collect
, karena jelas saya ingin koleksi baru menjadi Collection<Point>
tetapi saya tidak yakin bagaimana cara mendapatkan Pemasok untuk itu?
Sunting: Saya ingin dapat menggunakan fungsi ini dengan cara yang umum: jika saya meneruskannya Set saya mendapatkan Set sebagai gantinya, tetapi jika saya meneruskannya Daftar saya mendapatkan daftar sebagai gantinya. apakah mungkin melakukan ini?
Jawaban
Pilihan terbaik adalah tidak terlalu rumit, dan cukup lakukan:
public static Collection<Point> points2dToPoints(Collection<Point2D> points) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(Collectors.toList());
}
mengembalikan implementasi konkret antarmuka Collection
( misalnya, Collectors.toList()
) sambil bersembunyi dari luar rincian implementasi, ( yaitu, memiliki Collection
tanda tangan di metode).
Namun, Anda dapat membuat metode Anda lebih umum dengan meneruskannya - sebagai Supplier
- implementasi konkret dari antarmuka yang Collection
Anda inginkan untuk dikembalikan, yaitu
public static Collection<Point> points2dToPoints(Collection<Point2D> points, Supplier<Collection<Point>> aNew) {
return points.stream()
.map(Utils::point2dToPoint)
.collect(toCollection(aNew));
Dengan cara ini Anda bisa meneruskan Collection
implementasi konkret yang akan dikembalikan, misalnya:
points2dToPoints(.., ArrayList::new);
points2dToPoints(.., TreeSet::new);
Gantikan pernyataan itu Collectors.toCollection(() -> points)
dengan 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());
}
}
Keluaran:
Car [name=Toyota]
Car [name=Ford]
Car [name=Suzuki]