【问题标题】:Map over generic collection in Java 11 [duplicate]在 Java 11 中映射泛型集合 [重复]
【发布时间】:2020-11-27 20:18:50
【问题描述】:

我一直在尝试找到一种方法来编写泛型函数(可能不使用泛型)来映射集合。

假设我有一个函数 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&lt;Point&gt;,但我不确定如何为此获取供应商?

编辑:我希望能够以通用方式使用此函数:如果我将它传递给一个 Set 我会得到一个 Set 作为回报,但如果我将它传递一个 List 我会得到一个列表作为回报。甚至有可能做到这一点吗?

【问题讨论】:

  • 只需使用Collectors.toList()
  • @LouisWasserman 如果我不知道它是否是一个列表怎么办?我希望能够传递给它一个集合,并得到一个集合作为回报,但是当我传递一个列表时,我得到一个列表
  • 这是一个需要指定的重要细节。一般来说,不可能解决这个问题:你不能保证你得到的集合类型甚至可以由其他代码创建。您所能做的就是尝试捕捉常见情况:if (points instanceof Set) { // use toSet... }

标签: java generics collections java-11


【解决方案1】:

最好的选择是不要过于复杂,直接做:

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】:

    将声明 Collectors.toCollection(() -&gt; 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]
    

    【讨论】:

      猜你喜欢
      • 2021-12-12
      • 1970-01-01
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 1970-01-01
      • 1970-01-01
      • 2013-11-19
      相关资源
      最近更新 更多