-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
getAllPresent can return null values #176
Comments
ouch, if that's true doesn't HashMap break the Map contract? I'll try to play with your snippet and think about this when I have some time, but at first glance its an annoying break in the collections. |
/**
* Returns a {@link Set} view of the mappings 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 <tt>remove</tt> operation, or through the
* <tt>setValue</tt> operation on a map entry returned by the
* iterator) the results of the iteration are undefined. The set
* supports element removal, which removes the corresponding
* mapping from the map, via the <tt>Iterator.remove</tt>,
* <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
* <tt>clear</tt> operations. It does not support the
* <tt>add</tt> or <tt>addAll</tt> operations.
*
* @return a set view of the mappings contained in this map
*/
public Set<Map.Entry<K,V>> entrySet() {...} Since that's going through the APIs, I think my usage is correct and you might file a JDK bug? The iterator is supposed to be consistent. |
I also think that JDK behaviour is at least strange. There is a comment for setValue that could justify such behaviour:
But I presume it means the explicitly deleted entry cannot be edited. Will ask JDK guys. |
I verified that your program passes in JDK7. Have you opened up a JDK bug or shall I? |
I've submitted a bug report. Will give an update once have a feedback. |
Interesting note is that /**
* Sets our entry's value and writes through to the map. The
* value to return is somewhat arbitrary here. Since we do not
* necessarily track asynchronous changes, the most recent
* "previous" value could be different from what we return (or
* could even have been removed, in which case the put will
* re-establish). We do not and cannot guarantee more.
*/
public V setValue(V value) {
if (value == null) throw new NullPointerException();
V v = val;
val = value;
map.put(key, value);
return v;
} |
There are some minor problems:
Obvious.
This would make the next What's bothers me is the "unnecessary" table access, but In case of
The Javadoc for I guess, there's no solution. Calling I guess, insertions replacing regular nodes by tree nodes can break the entry the same way. |
It's unfortunate that they untreeify. They don't shrink the capacity on removal by assuming the high watermark will occur again or the map will be short lived. It seems that their optimization makes the opposite assumption and breaks backwards compatibility to do so. |
Any update? |
No updates so far |
@Maaartinus I think your example might be flawed because it assumes that writes to the map are visible to the entry. An entry's state should be a stable snapshot, outside of any direct mutations, and is not expected to change underneath the consumer. The collection classes tend to hand back a write-through entry rather than their internal one for this purpose.
So I think the current behavior is correct, but perhaps subtle, detail of the Collections Framework. |
@ben-manes But an entry is neither a view into the map (as my example shows), nor a stable snapshot (just replace the 10 in my example by a smaller value). Speaking about "some point at or since the creation of the iterator" allows both kinds of behavior and even its mix. In the javadoc for It should be explicitly stated, that any change to the map since this entry was returned, makes the result of |
In the case of |
Ticket created: |
Thanks! I'll try to find the time to get this fixed and released. Great catch, btw. |
Looks like the changes passed CI and its ready for release. I can do that now if this is impacting you in any way. If not, then I'll wait a little for #177 to see if there is another issue to fix. Since version numbers are free I am fine getting this to you, so please let me know. |
Thanks for a fix! It's not critical for me so feel free to release later. |
Released! |
@DougLea fixed the jdk bug, so I’ll revisit this optimization in the future. |
Thanks. |
This restores an optimization that was removed in #176 due to a bug in older JDKs.
This restores an optimization that was removed in #176 due to a bug in older JDKs.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
This restores an optimization that was removed in #176 due to a bug in Java 8.
Looks like using Iterator.remove before Entry.setValue is not correct. remove can substitute some TreeNodes in HashMap to plain Nodes, while iterator continues to iterate over old TreeNode instances and sets the values to those garbage nodes.
The text was updated successfully, but these errors were encountered: