我实现了一个函数,返回 Map<key,Set<objects>>
当我调用这个函数时,它返回的是类型为Unmodifiable的集合,我需要对这些集合进行一些操作,如何将它们转换为可修改的集合?
我需要对这些集合进行一些操作,如何将它们转换为可修改的集合才是最佳实践?否则我得到
Exception in thread "main" java.lang.UnsupportedOperationException
谢谢。
假设 Map
本身是可变的,你可以使用类似
map.replaceAll((key, set) -> new HashSet<>(set));
例子。
Map<Integer,Set<Object>> map = new HashMap<>();
map.put(5, Collections.emptySet());
map.put(10, Collections.singleton("foo"));
map.replaceAll((key, set) -> new HashSet<>(set));
map.get(5).add(42);
map.get(10).add("bar");
map.entrySet().forEach(System.out::println);
5=[42]
10=[bar, foo]
当然,你也可以用 new HashSet<>(set)
与 new TreeSet<>(set)
或一般 Set
实现类型遵循复制构造函数的约定。当你不能使用复制构造函数时,你必须使用 addAll
例如:
map.replaceAll((key, set) -> {
TreeSet<Object> newSet = new TreeSet<>(Comparator.comparing(Object::toString));
newSet.addAll(set);
return newSet;
});
还有一种选择。不是转换地图的所有值,而是只在需求时转换集合,即当你真正想修改它们,结果发现它们没有预期的类型。
Map<Integer,Set<Object>> map = new HashMap<>();
map.put(5, Collections.emptySet());
map.put(10, Collections.singleton("foo"));
map.computeIfPresent(5, (key,set)->set instanceof HashSet? set: new HashSet<>()).add(42);
map.computeIfPresent(10, (key,set)->set instanceof HashSet?set:new HashSet<>()).add("bar");
map.entrySet().forEach(System.out::println);
你可以复制 变成另一个可以修改的集子.
类似这样。
Set<YourType> newSet = unmodifiableSet
.stream()
.collect(Collectors.toSet());
// Or maybe...
Set<YourTYpe> otherSet = new HashSet<>();
otherSet.addAll(unmodifiableSet);
然后,你就可以顺利地修改新的列表,并将其重新分配到地图中。
对于一个 HashSet
:
Set<Type> modifiable = new HashSet<>(unmodifiable);
用于: TreeSet
:
SortedSet<Type> modifiable = new TreeSet<>(unmodifiable);
用于: LinkedHashSet
:
Set<Type> modifiable = new LinkedHashSet<>(unmodifiable);
如果你使用了一个花哨的Set实现,而没有这样的构造函数。
Set<Type> modifiable = new MyFancySet<>();
modifiable.addAll(unmodifiable);
你可以把它作为一个单行线,用 Streams
:
有 map
作为你的原始地图 Map<Integer, ImmutableSet<Object>> map;
)
Map<Integer, Set<Object>> mutableMap = map.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, Sets::newHashSet));