Java 11의 일반 컬렉션에 대한 매핑 [중복]

Nov 28 2020

나는 제네릭을 사용하지 않는 제네릭 함수를 작성하여 컬렉션을 매핑하는 방법을 찾으려고 노력해 왔습니다.

A에서 B까지의 함수가 있다고 가정 해 보겠습니다 . a를 받아서 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>하지만 공급자를 얻는 방법을 잘 모르겠 기 때문입니다.

편집 :이 함수를 일반적인 방식으로 사용할 수 있기를 원합니다. 세트를 전달하면 세트가 반환되지만 목록을 전달하면 목록이 반환됩니다. 이것이 가능합니까?

답변

3 dreamcrash Nov 28 2020 at 03:32

The best option is to not overcomplicate, and simply do:

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

returning a concrete implement of interface Collection (e.g., Collectors.toList()) while hiding from the outside the implementation details, (i.e., having Collection in the method signature).

You can, however, make your method more generic by passing to it -- as Supplier -- which concrete implementation of the interface Collection you want it to return, namely

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

In this way you can pass the concrete Collection implementation that will be returned, for example:

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

Replace the statement Collectors.toCollection(() -> points) with 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());    
    }
}

Output:

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