Java:通用过滤器映射函数

ope*_*sas 3 java clone map filter

我正在尝试开发一个通用函数来过滤地图.

我到目前为止的代码是:

public static Map<?, ?> filterAttrs(Map<?, ?> args, String... unless) {

    Map<?, ?> filteredAttrs = Map.class.newInstance();

    Arrays.sort(unless);
    for (Object o : args.keySet()) {
        if (Arrays.binarySearch(unless, o.toString()) < 0 ) {
            filteredAttrs.put(o, args.get(o));
        }
    }
    return filteredAttrs;
}
Run Code Online (Sandbox Code Playgroud)

我在filteredAttrs.put中收到以下错误

在Map类型中放置(捕获#5-of?,捕获#6-of?)的方法不适用于参数(对象,捕获#8-of?)

我不知道如何实例化泛型Map(我尝试使用1Map.class.newInstance()`).

有任何想法吗?

编辑:在阅读了许多答案后,问题似乎是如何使filteredAttrs一个类型相同的实例args.(Map) args.getClass().newInstance()似乎可以做到这一点.

tem*_*def 8

此代码的问题在于类型系统阻止您将对象放入Map其键类型的对象中?.这是因为如果键类型是?,编译器不知道实际存储在地图中的是什么 - 它可能是Object,或者Integer,或者List<Object>- 因此它无法确认您尝试添加到地图中的是什么正确的类型,并不会在不合适的地方Map.例如,如果您有此方法:

public static void breakMyMap(Map<?, ?> m) {
    m.put(new Object(), new Object()); // Won't compile
}
Run Code Online (Sandbox Code Playgroud)

然后编写如下代码:

Map<String, String> myMap = new HashMap<String, String>();
breakMyMap(myMap);
Run Code Online (Sandbox Code Playgroud)

然后,如果breakMyMap要编译的代码,它会将一对Objects作为键和值放入a中Map<String, String>,打破所有元素确实是Strings 的不变量.

要解决此问题Map<?, ?>,请更改函数,以便获得有关键和值的更多类型信息,而不是使此功能起作用.例如,你可以试试这个:

public static <K, V> Map<K, V> filterAttrs(Map<K, V> args, String... unless) {

    Map<K, V> filteredAttrs = new HashMap<K, V>();

    Arrays.sort(unless);
    for (K o : args.keySet()) {
        String attr = o.toString();
        if (Arrays.binarySearch(unless, o.toString()) < 0 ) {
            filteredAttrs.put(o, args.get(o));
        }
    }
    return filteredAttrs;
}
Run Code Online (Sandbox Code Playgroud)

既然编译器知道密钥类型K,它就可以验证put不会混淆映射中键的类型.

我应该指出的另一件事是你所拥有的代码即使编译也不会有效.原因是这条线

Map<?, ?> filteredAttrs = Map.class.newInstance();
Run Code Online (Sandbox Code Playgroud)

将在运行时导致异常,因为它Map是一个接口,而不是一个类,因此尝试使用它newInstance来创建它的实例将无法正常工作.要解决这个问题,您可以显式指定地图的类型(正如我在上面的代码中所做的那样),或者获取参数的类:

Map<K, V> filteredAttrs = args.getClass().newInstance();
Run Code Online (Sandbox Code Playgroud)

当然,这也不保证可以工作,尽管集合的一般合同是所有集合都应该有一个无参数的构造函数.

希望这可以帮助!


Mar*_*gus 5

如果人们重新发明轮子(并没有做得更好),我认为这是不好的.

要在一个建议中修复所有问题:您可以尝试Google Guava吗?

例如,您可以使用地图:

  • Maps.filterEntries
  • Maps.filterKeys
  • Maps.filterValues

或者至少编写一个以谓词为参数的过滤器.