Java 泛型 – 不兼容的等式约束

huangapple go评论96阅读模式
英文:

Java generics - incompatible equality constraint

问题

以下是翻译好的部分:

我正试图将一个地图筛选为其自身的子集。为了实现这一点,我尝试实现了以下的 utils 方法:

/**
 * 减小地图的大小。从地图中的第一个条目开始。
 * @param map 地图。
 * @param size 要减小地图的大小。
 * @return 减小大小后的地图。
 */
public static <T> Map<T, T> subList(@NonNull Map<T, T> map, int size) {
  val sub = new HashMap<T, T>();
  for (Map.Entry<T, T> entry : map.entrySet()) {
      if (sub.size() > size) {
          break;
      }

      sub.put(entry.getKey(), entry.getValue());
  }
  return sub;
}

然后我尝试像这样使用它:

@Override
public Set<FileTransfer> upload(@NonNull ConnectionConfiguration target, @NonNull Map<FileTransfer, File> fileExports) {
    val batchSize = getBatchSize();
    if (fileExports.size() > batchSize) {
        fileExports = (Map<FileTransfer, File>) MapUtils.subList(fileExports, batchSize);
    }

    ...
}

但我收到了错误:

原因:不兼容的相等约束:FileTransfer 和 File

我本以为我可以传递一个 Map<FileTransfer, File> 给这个方法,因为这两种类型都扩展自 Object。我在这里做错了什么?

英文:

I am attempting to filter down a map to a sub set of itself. To achieve this I have attempted to implement the following utils method:

/**
* Reduces the size of the map. Starts from the first entry in the map.
* @param map The map.
* @param size The size to reduce the map by.
* @return The reduced size map.
*/
public static &lt;T&gt; Map&lt;T, T&gt; subList(@NonNull Map&lt;T, T&gt; map, int size) {
  val sub = new HashMap&lt;T, T&gt;();
  for (Map.Entry&lt;T, T&gt; entry : map.entrySet()) {
      if (sub.size() &gt; size) {
          break;
      }

      sub.put(entry.getKey(), entry.getValue());
  }
  return sub;
}

I am then attempting to use it like this:

@Override
public Set&lt;FileTransfer&gt; upload(@NonNull ConnectionConfiguration target, @NonNull Map&lt;FileTransfer, File&gt; fileExports) {
    val batchSize = getBatchSize();
    if (fileExports.size() &gt; batchSize) {
        fileExports = (Map&lt;FileTransfer, File&gt;) MapUtils.subList(fileExports, batchSize);
    }

    ...
}

But I am getting the error:

> reason: Incompatible equality constraint: FileTransfer and File

I had assumed that I could pass a Map&lt;FileTransfer, File&gt; to the method because both types extend Object. What am I doing wrong here?

答案1

得分: 2

subList接受一个Map<K, V>。请注意,这两个泛型参数是相同的,因此您只能传递诸如Map<Integer, Integer>Map<String, String>Map<FileTransfer, FileTransfer>之类的内容。您正在尝试传递Map<FileTransfer, File>,其泛型参数不同。

您应该重新编写subList方法,使其接受一个Map<K, V>。现在请注意,泛型参数是不同的,因此可以传递具有不同键类型和值类型的映射。

public static <K, V> Map<K, V> subList(@NonNull Map<K, V> map, int size) {
  val sub = new HashMap<K, V>();
  for (Map.Entry<K, V> entry : map.entrySet()) {
      if (sub.size() > size) {
          break;
      }

      sub.put(entry.getKey(), entry.getValue());
  }
  return sub;
}

现在您甚至不需要在调用方进行强制转换:

fileExports = MapUtils.subList(fileExports, batchSize);
英文:

subList accepts a Map&lt;T, T&gt;. Note that the two generic parameters are the same, so you can only pass things like Map&lt;Integer, Integer&gt;, Map&lt;String, String&gt; or Map&lt;FileTransfer, FileTransfer&gt;. You are trying to pass Map&lt;FileTransfer, File&gt;, which has different generic parameters.

You should rewrite the subList method so that it accepts a Map&lt;K, V&gt;. Note now that the generic parameters are different, so maps with different key type and value type can be passed in.

public static &lt;K, V&gt; Map&lt;K, V&gt; subList(@NonNull Map&lt;K, V&gt; map, int size) {
  val sub = new HashMap&lt;K, V&gt;();
  for (Map.Entry&lt;K, V&gt; entry : map.entrySet()) {
      if (sub.size() &gt; size) {
          break;
      }

      sub.put(entry.getKey(), entry.getValue());
  }
  return sub;
}

Now you don't even need the cast at the caller's side:

fileExports = MapUtils.subList(fileExports, batchSize);

huangapple
  • 本文由 发表于 2020年4月10日 17:19:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/61137309.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定