Is modifying the key set of a map okay, or is it an abuse of a map in Java with undefined behavior?

huangapple go评论81阅读模式
英文:

Is modifying the key set of a map okay, or is it an abuse of a map in Java with undefined behavior?

问题

我注意到我们可以在Java中操纵映射中的键集。

例如,在这里,我们复制了一个映射,然后通过调用Set:retainAll来有效地通过修改键集合来删除一些条目。

Map< DayOfWeek , String > dailyAssignment = new EnumMap<>( DayOfWeek.class ) ;
dailyAssignment.put( DayOfWeek.MONDAY, "Alice" ) ;
dailyAssignment.put( DayOfWeek.TUESDAY, "Bob" ) ;
dailyAssignment.put( DayOfWeek.SATURDAY, "Bob" ) ;
dailyAssignment.put( DayOfWeek.SUNDAY, "Carol" ) ;

List< DayOfWeek > weekend = List.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY ) ;

Map< DayOfWeek , String > weekendAssignment = new EnumMap<>( dailyAssignment ) ;
weekendAssignment.keySet().retainAll( weekend ) ;

输出到控制台。

System.out.println( "dailyAssignment.toString(): " + dailyAssignment ) ;
System.out.println( "weekendAssignment.toString(): " + weekendAssignment ) ;

这似乎起作用,在Java 12中看到在 IdeOne.com 上实时运行

dailyAssignment.toString(): {MONDAY=Alice, TUESDAY=Bob, SATURDAY=Bob, SUNDAY=Carol}

weekendAssignment.toString(): {SATURDAY=Bob, SUNDAY=Carol}

➥ 虽然它似乎起作用,但这是否是在映射的键集中正确的使用方式?EnumMap::keySet 方法的Javadoc没有涉及返回的键集的可变性。

英文:

I noticed that we can manipulate the set of keys in a map in Java.

For example, here we copy a map, then effectively remove some of the entries by modifying the set of keys with a call to Set:retainAll.

Map&lt; DayOfWeek , String &gt; dailyAssignment = new EnumMap&lt;&gt;( DayOfWeek.class ) ;
dailyAssignment.put( DayOfWeek.MONDAY, &quot;Alice&quot; ) ;
dailyAssignment.put( DayOfWeek.TUESDAY, &quot;Bob&quot; ) ;
dailyAssignment.put( DayOfWeek.SATURDAY, &quot;Bob&quot; ) ;
dailyAssignment.put( DayOfWeek.SUNDAY, &quot;Carol&quot; ) ;

List&lt; DayOfWeek &gt; weekend = List.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY ) ;

Map&lt; DayOfWeek , String &gt; weekendAssignment = new EnumMap&lt;&gt;( dailyAssignment ) ;
weekendAssignment.keySet().retainAll( weekend ) ;

Dump to console.

System.out.println( &quot;dailyAssignment.toString(): &quot; + dailyAssignment ) ;
System.out.println( &quot;weekendAssignment.toString(): &quot; + weekendAssignment ) ;

This seems to work, as seen in Java 12 when run live at IdeOne.com.

>dailyAssignment.toString(): {MONDAY=Alice, TUESDAY=Bob, SATURDAY=Bob, SUNDAY=Carol}

>weekendAssignment.toString(): {SATURDAY=Bob, SUNDAY=Carol}

➥ While it seems to work, is this a proper use of a key set in a map? The Javadoc for EnumMap::keySet method does not address mutability of the returned key set.

答案1

得分: 2

是的,对于在Map中对键的Set进行变异是一个受支持的特性。

请查阅Map的Javadoc,而不是其实现EnumMapMap::keySet文档明确指出,修改键集合是一种可接受的方式来改变映射。

引用Map::keySet的Javadoc:…该集合支持元素移除…

>返回包含在此映射中的键的Set视图。该集合由映射支持,因此映射的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射(除非通过迭代器自己的删除操作),迭代的结果是未定义的。该集合支持元素移除,可以通过Iterator.removeSet.removeremoveAllretainAllclear操作从映射中删除相应的映射。它不支持添加或添加所有操作。

英文:

Yes, mutating the Set of keys in a Map is a supported feature.

Look the Javadoc of Map rather than its implementation EnumMap. The Map::keySet documentation specifically states that altering the set of keys is an acceptable way to mutate the map.

To quote Map::keySet Javadoc: …The set supports element removal…

>Returns a Set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are undefined. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

huangapple
  • 本文由 发表于 2020年7月27日 07:08:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/63106697.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定