简体   繁体   English

Java - 将 map(key, set) 中的不可修改集转换为可修改集

[英]Java - convert unmodifiable sets in a map(key, set) to modifaible

I implemented a function which return Map<key,Set<objects>> , when I call this function it return the sets with type Unmodifiable.我实现了一个返回Map<key,Set<objects>>的 function ,当我调用这个 function 时,它返回类型为不可修改的集合。

I need to do some operations to this sets, how to convert them to modifiable sets in best practice?我需要对这个集合做一些操作,如何在最佳实践中将它们转换为可修改的集合? Otherwise I got否则我得到

Exception in thread "main" java.lang.UnsupportedOperationException

Thanks in advance.提前致谢。

Assuming that the Map itself is mutable, you use something like假设Map本身是可变的,你使用类似

map.replaceAll((key, set) -> new HashSet<>(set));

Example:例子:

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]

Of course, you can also replace new HashSet<>(set) with new TreeSet<>(set) or generally every Set implementation type following the copy constructor convention.当然,您也可以将new HashSet<>(set)替换为new TreeSet<>(set)或通常遵循复制构造函数约定的每个Set实现类型。 When you can't use a copy constructor, you have to resort to addAll , eg当您不能使用复制构造函数时,您必须求助于addAll ,例如

map.replaceAll((key, set) -> {
    TreeSet<Object> newSet = new TreeSet<>(Comparator.comparing(Object::toString));
    newSet.addAll(set);
    return newSet;
});

There's another option.还有另一种选择。 Instead of converting all values of the map, only convert the sets on demand, ie when you actually want to modify them and they turn out not to have the intended type:与其转换 map 的所有值,不如仅按需转换集合,即当您实际想要修改它们但结果却没有预期的类型时:

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);

You could copy the original set to another one that can be modified .您可以将 原始集复制到另一个可以修改的集。

Something like this:像这样的东西:

Set<YourType> newSet = unmodifiableSet
                        .stream()
                        .collect(Collectors.toSet());
// Or maybe...
Set<YourTYpe> otherSet = new HashSet<>();
otherSet.addAll(unmodifiableSet);

Then, you could modify the new list without any problem, and re-assign it into the map.然后,您可以毫无问题地修改新列表,并将其重新分配到 map。

Just use the copy constructor只需使用复制构造函数

For a HashSet :对于HashSet

Set<Type> modifiable = new HashSet<>(unmodifiable);

For a TreeSet :对于TreeSet

SortedSet<Type> modifiable = new TreeSet<>(unmodifiable);

For a LinkedHashSet :对于LinkedHashSet

Set<Type> modifiable = new LinkedHashSet<>(unmodifiable);

If you use a fancy Set implementation without such constructor:如果您使用没有此类构造函数的精美 Set 实现:

Set<Type> modifiable = new MyFancySet<>();
modifiable.addAll(unmodifiable);

You can do that as a one-liner with Streams :您可以使用Streams执行此操作:

With map being your original map (eg Map<Integer, ImmutableSet<Object>> map; ) map是您原来的 map (例如Map<Integer, ImmutableSet<Object>> map;

Map<Integer, Set<Object>> mutableMap = map.entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, Sets::newHashSet));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM