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()似乎可以做到这一点.
此代码的问题在于类型系统阻止您将对象放入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)
当然,这也不保证可以工作,尽管集合的一般合同是所有集合都应该有一个无参数的构造函数.
希望这可以帮助!
如果人们重新发明轮子(并没有做得更好),我认为这是不好的.
要在一个建议中修复所有问题:您可以尝试Google Guava吗?
例如,您可以使用地图:
或者至少编写一个以谓词为参数的过滤器.
| 归档时间: |
|
| 查看次数: |
5311 次 |
| 最近记录: |