为 toArray 方法创建通用数组

3
我有以下方法:

我有以下方法:

public static <T, U> T[] getKeysForValue(Map<T,U> map,U value){
    if(map == null || map.isEmpty()) {
        return null;
    }

    Set<T> keys = new HashSet<T>();

    for (Map.Entry<T,U> entry : map.entrySet()) {
        if (entry.getValue().equals(value)) {
            keys.add(entry.getKey());
        }
    }

    return keys.toArray(new T[keys.size()]);
}

我在keys.toArray(new T[keys.size()])这一行遇到了编译错误,提示“无法创建T的泛型数组”,这很明显。我该如何解决这个问题?


6
一个更长、实用的回答会更好。Java泛型系统中一些明显的缺陷可以通过使用显式类型标记来解决。不幸的是,当类型参数本身被参数化时,这些标记并没有帮助,但这里并非如此。不知道如何在Java中做这件事不是恶意挑衅的好借口。 - millimoose
@feralin 我在C#和Java方面拥有同等的专业知识,因此将它们进行比较是非常有争议的。 - Tapas Bose
@millimoose 为什么你说我在逗乐?你能否提供一些证据或证明吗? - feralin
2
@feralin,你的评论至少与“答案是你的语言很糟糕”非常接近。由于意图无法在互联网上传递,我没有“证据”,但我们又不在法庭上。此外,对此进行细微的分析忽略了我反对的核心,即你的评论并不是非常建设性的。 - millimoose
2个回答

5
为什么不直接返回Set呢?在这个场景下,这样做更加合理。
public static <T, U> Set<T> getKeysForValue(Map<T, U> map, U value) {
    ...

    return keys;
}

如果您仍希望返回一个数组,另一种选择是将一个数组作为参数传递,并填充它:
public static <T, U> T[] getKeysForValue(Map<T,U> map, U value, T[] dest) {
    ...

    return keys.toArray(dest);
}

4
你应该将与 T 对应的类作为参数传递给你的方法,并调用 Array.newInstance(clazz, size)
public static <T, U> T[] getKeysForValue(Class<T> clazz, Map<T,U> map,U value){

  T[] array = (T[])Array.newInstance(clazz, size);

没有传递clazz就没有办法吗?通过在运行时确定键的类类型,我不能这样做吗? - Tapas Bose
不行,因为在泛型中存在类型擦除,所以在运行时无法知道类型,因此你没有猜测的机会。在运行时,Map<T,U> 基本上变成了 Map<Object, Object> - Arnaud Denoyelle
+1,还有其他的方法,我自己回答了。在这之前我应该再尝试一下的。 :-) - Tapas Bose
可能想要使用@SuppressWarnings("unchecked") - arshajii
1
如果调用者没有T类,那么这个方法是行不通的(T是调用者中的类型变量)。我们无法通过所有API传递类。更好的答案是-不要使用数组,而是使用集合。 - ZhongYu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接