我实现了一个返回函数Map<key,Set<objects>>
,当我调用这个函数时,它返回类型为不可修改的集合。
我需要对这个集合做一些操作,如何在最佳实践中将它们转换为可修改的集合?否则我得到
Exception in thread "main" java.lang.UnsupportedOperationException
提前致谢。
我实现了一个返回函数Map<key,Set<objects>>
,当我调用这个函数时,它返回类型为不可修改的集合。
我需要对这个集合做一些操作,如何在最佳实践中将它们转换为可修改的集合?否则我得到
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);
对于一个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);
您可以将原始集复制到另一个可以修改的集。
像这样的东西:
Set<YourType> newSet = unmodifiableSet
.stream()
.collect(Collectors.toSet());
// Or maybe...
Set<YourTYpe> otherSet = new HashSet<>();
otherSet.addAll(unmodifiableSet);
然后,您可以毫无问题地修改新列表,并将其重新分配到地图中。
您可以使用以下方法作为单线器来做到这一点Streams
:
map
成为您的原始地图(例如Map<Integer, ImmutableSet<Object>> map;
)
Map<Integer, Set<Object>> mutableMap = map.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, Sets::newHashSet));