【问题标题】:Why does the Java mapFactory argument of the method toMap in the Collectors class need the types to be specified? [duplicate]为什么 Collectors 类中 toMap 方法的 Java mapFactory 参数需要指定类型? [复制]
【发布时间】:2020-05-27 10:01:40
【问题描述】:

以下代码不能用我的JDK14编译:

Map<Integer, String> map = Arrays.asList("this", "is", "just", "an", "example").stream()
    .collect(Collectors.toMap(w -> w.length(),
                              w -> w,
                            (existing, replacement) -> replacement,
                            () -> new TreeMap<>(Comparator.reverseOrder())));

如果我为 TreeMap 的构造函数指定类型,它可以正常工作:

Map<Integer, String> map4 = Arrays.asList("this", "is", "just", "an", "example").stream()
    .collect(Collectors.toMap(w -> w.length(),
                              w -> w,
                            (existing, replacement) -> replacement,
                            () -> new TreeMap<Integer, String>(Comparator.reverseOrder())));

是我遗漏了什么还是 JDK14 的类型擦除系统中存在错误?

【问题讨论】:

  • 编译器的错误信息是否类似于“无法派生类型”?
  • 是的,“无法推断类型变量”。

标签: java types java-stream collectors java-14


【解决方案1】:

在链式调用的情况下,推断Comparator 的类型似乎存在问题。

如果您事先创建地图供应商,它可能会起作用(顺便说一句,不仅在 JDK14 中):

Supplier<Map<Integer, String>> supplier = () -> new TreeMap<>(Comparator.reverseOrder());

Map<Integer, String> mapWithSupplier = Arrays.asList("this", "is", "just", "an", "example").stream()
                .collect(Collectors.toMap(w -> w.length(),
                        w -> w,
                        (existing, replacement) -> replacement,
                        supplier));

如果您使用Collections.reverseOrder(),则根本不会遇到此问题:

Map<Integer, String> mapCollectionReversed = Arrays.asList("this", "is", "just", "an", "example").stream()
                .collect(Collectors.toMap(w -> w.length(),
                        w -> w,
                        (existing, replacement) -> replacement,
                        () -> new TreeMap<>(Collections.reverseOrder())));

或者至少事先创建了一个比较器:

Comparator<Integer> comparator = Comparator.reverseOrder();

Map<Integer, String> mapWithComparator = Arrays.asList("this", "is", "just", "an", "example").stream()
                .collect(Collectors.toMap(w -> w.length(),
                        w -> w,
                        (existing, replacement) -> replacement,
                        () -> new TreeMap<>(comparator)));

如果没有reverseOrder,可以使用TreeMap::new成功创建地图:

Map<Integer, String> map = Arrays.asList("this", "is", "just", "an", "example").stream()
                .collect(Collectors.toMap(w -> w.length(),
                        w -> w,
                        (existing, replacement) -> replacement,
                        TreeMap::new));

【讨论】:

  • 好的,但问题是为什么 Java 编译器不能推断 TreeMap 的类型。当一个人将引用传递给构造函数时,它会这样做,就像你的例子一样。
  • 当比较器传递给地图构造函数时,推断比较器的类型似乎存在问题 - 请检查更新
猜你喜欢
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2013-05-28
  • 1970-01-01
  • 2015-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多