Java泛型放在Map >

时间:2021-05-18 17:30:45

Is there a way to make the following implementation in a type safe manner?

有没有办法以类型安全的方式进行以下实现?

public void myMethod( Map<String, ? extends List<String>> map )
{
   map.put("foo", Collections.singletonList("bar");
}

The above implementation doesn't work. It requires a Map<String, ? super List<String>> to compile the method map.put() correctly. But myMethod won't accept any subtype of List this way. So, I have to use Map<String, ? extends List<String>> instead. How can I solve this problem in a type safe manner?

上述实现不起作用。它需要Map >正确编译方法map.put()。但是myMethod不会以这种方式接受List的任何子类型。所以,我必须使用Map >。如何以类型安全的方式解决此问题?

4 个解决方案

#1


public void myMethod( Map<String, List<String>> map ) {
    map.put("foo", Collections.singletonList("bar") );
}

You can't put a List (the return type of Collections.singletonList() into a Map of ? extends List since the actual type could be any implementation of List. For example, it is not safe to put a generic List into a Map<String,LinkedList> since the List might not be a LinkedList. However, we can easily put a LinkedList into a Map of <String,List>.

您不能将List(Collections.singletonList()的返回类型放入?extends List的Map中,因为实际类型可能是List的任何实现。例如,将通用List放入Map中是不安全的。 ,因为List可能不是LinkedList。但是,我们可以轻松地将LinkedList放入 的Map中。 ,list> ,linkedlist>

I think you were over thinking your generics. You do not have to use ? extends for a non-generic class. For example, List<Object> will hold any Object, the ? extends is not needed to add an object. A List<List<Foo>> will only take List<Foo> objects and not List<FooSubclass> objects [Generic classes don't inherit based on their parameters]. This is where ? extends comes into play. To add both List<Foo> and List<FooSubclass> to a List, the type must be List<List<? extends Foo>>.

我想你已经在考虑你的仿制药了。你不必使用?扩展为非泛型类。例如,List 将保存任何Object,?不需要extends来添加对象。 List >只接受List 对象而不是List 对象[通用类不会根据它们的参数继承]。这是哪里 ?延伸发挥作用。要将List 和List 添加到List,类型必须是List >。

#2


Wouldn't Map<String, List<String> work? Is there some particular reason you have to have a wildcard there at all?

Map 不会工作吗?有什么特别的原因你必须在那里有一个通配符吗? ,list>

#3


There is a very simple principle when using Collections and Generics together. It is called "The Get and The Put Principle":

将Collections和Generics一起使用时,有一个非常简单的原则。它被称为“获取和放置原则”:

Use an "extends" wildcard when you only GET values out of a collection, use "super" wildcard when you only PUT values into a collection and don't use any wildcard when you want both get and put.

当你只从集合中获取值时使用“扩展”通配符,当你只将PUT值放入集合时使用“超级”通配符,当你想要get和put时不使用任何通配符。

So, as you can see, the initial example is invalid, according to this principle.

所以,正如你所看到的,根据这个原则,最初的例子是无效的。

#4


Imagine if someone passed you a Map<String, ArrayList<String>>. The value you're putting in is the result of Collections.singletonList which is not an ArrayList.

想象一下,如果有人传给你一个Map >。您输入的值是Collections.singletonList的结果,它不是ArrayList。 ,arraylist>

You cannot accept any subtype of List in the Map and then expect to be able to add your own, possibly incompatible, subtype.

您不能在Map中接受List的任何子类型,然后期望能够添加您自己的,可能不兼容的子类型。

#1


public void myMethod( Map<String, List<String>> map ) {
    map.put("foo", Collections.singletonList("bar") );
}

You can't put a List (the return type of Collections.singletonList() into a Map of ? extends List since the actual type could be any implementation of List. For example, it is not safe to put a generic List into a Map<String,LinkedList> since the List might not be a LinkedList. However, we can easily put a LinkedList into a Map of <String,List>.

您不能将List(Collections.singletonList()的返回类型放入?extends List的Map中,因为实际类型可能是List的任何实现。例如,将通用List放入Map中是不安全的。 ,因为List可能不是LinkedList。但是,我们可以轻松地将LinkedList放入 的Map中。 ,list> ,linkedlist>

I think you were over thinking your generics. You do not have to use ? extends for a non-generic class. For example, List<Object> will hold any Object, the ? extends is not needed to add an object. A List<List<Foo>> will only take List<Foo> objects and not List<FooSubclass> objects [Generic classes don't inherit based on their parameters]. This is where ? extends comes into play. To add both List<Foo> and List<FooSubclass> to a List, the type must be List<List<? extends Foo>>.

我想你已经在考虑你的仿制药了。你不必使用?扩展为非泛型类。例如,List 将保存任何Object,?不需要extends来添加对象。 List >只接受List 对象而不是List 对象[通用类不会根据它们的参数继承]。这是哪里 ?延伸发挥作用。要将List 和List 添加到List,类型必须是List >。

#2


Wouldn't Map<String, List<String> work? Is there some particular reason you have to have a wildcard there at all?

Map 不会工作吗?有什么特别的原因你必须在那里有一个通配符吗? ,list>

#3


There is a very simple principle when using Collections and Generics together. It is called "The Get and The Put Principle":

将Collections和Generics一起使用时,有一个非常简单的原则。它被称为“获取和放置原则”:

Use an "extends" wildcard when you only GET values out of a collection, use "super" wildcard when you only PUT values into a collection and don't use any wildcard when you want both get and put.

当你只从集合中获取值时使用“扩展”通配符,当你只将PUT值放入集合时使用“超级”通配符,当你想要get和put时不使用任何通配符。

So, as you can see, the initial example is invalid, according to this principle.

所以,正如你所看到的,根据这个原则,最初的例子是无效的。

#4


Imagine if someone passed you a Map<String, ArrayList<String>>. The value you're putting in is the result of Collections.singletonList which is not an ArrayList.

想象一下,如果有人传给你一个Map >。您输入的值是Collections.singletonList的结果,它不是ArrayList。 ,arraylist>

You cannot accept any subtype of List in the Map and then expect to be able to add your own, possibly incompatible, subtype.

您不能在Map中接受List的任何子类型,然后期望能够添加您自己的,可能不兼容的子类型。