我有以下映射:Map<String, Set<String>>
,我需要初始化它。这本身不是问题所在。然而,由于我希望Set
保持插入顺序,我曾想过用new LinkedHashMap<String, LinkedHashSet<String>>();
初始化整个结构,但这迫使我将映射更改为:Map<String, LinkedHashSet<String>>
。
如果我在初始化时指定了特定类型,为什么我不能使用接口?或者,确保实现嵌套类型的更好方法是什么?
为了更容易理解我为什么要这么做,下面是代码:
private void sortMap(Map<String, Map<Date, Map<String, Long>>> dataMap) {
Map<String, Set<String>> sortedNames = new LinkedHashMap<String, Set<String>>(); // <-- this initialization
for (Map.Entry<String, Map<Date, Map<String, Long>>> entry : dataMap.entrySet()) {
sortedNames.put(entry.getKey(), entry.getValue().get(getCurrentMonthDate()).keySet());
}
}
编辑
在公认答案的帮助下,我想出了这个似乎对我来说很好的解决方案:
Map<String, Set<String>> sortedNames = dataMap.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry<String, LinkedHashSet<String>>(e.getKey(),
e.getValue().get(getCurrentMonthDate()).keySet().stream()
.collect(Collectors.toCollection(LinkedHashSet<String>::new))))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
泛型类型不是协变的,因此不能将LinkedHashMap<String, LinkedHashSet<String>>
分配给Map<String, Set<String>>
。
如果需要强制映射值仅为LinkedHashSet
,则必须将映射声明为Map<String, LinkedHashSet<String>>
。
然而,这不应该是必要的,因为您可以用Set<String>
:的子类型调用map.put
Map<String, Set<String>> map = new LinkedHashMap<>();
map.put("key", new LinkedHashSet<String>());
这仍然允许您对Set
接口进行编程。
下面是使用流API的代码的更简单版本。
Date curretMonthDate = getCurrentMonthDate();
Map<String, Set<String>> sortedNames = dataMap.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry<String, LinkedHashSet<String>>(e.getKey(),
e.getValue()
.entrySet()
.stream()
.filter(inner -> inner.getKey().equals(curretMonthDate))
.flatMap(subEntry -> subEntry
.getValue()
.entrySet()
.stream()
.map(Entry::getKey))
.collect(Collectors.toCollection(LinkedHashSet<String>::new))))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
初始化如下。
Map<String, Set<String>> test = new LinkedHashMap<>();
// initialize to LinkedHashSet<> when putting elements
test.put("key", new LinkedHashSet<>());
不能使用Map<String, Set<String>> test = new LinkedHashMap<String, LinkedHashSet<String>>()
,因为LinkedHashMap<String, LinkedHashSet<String>>();
不是Map<String, Set<String>>
的子类型。
如果不使用通配符,并不是说Java中的泛型类型不是协变或逆变。