Skip to content

Commit

Permalink
Faster LinkedHashMap tail() (#2725)
Browse files Browse the repository at this point in the history
Change: LinkedHashMap tail() is now constant-time, from being O(size)
time and space.

Motivation: We have a use case which looks somewhat like the following.

1. It's effectively a Queue use case (fifo).
2. Iteration order needs to be stable.
3. Elements in the queue frequently need to be verified as present in
   the queue.
4. Occasionally, removals must occur, which are usually from the head of
   the queue although occasionally randomly.

We started with a Queue and eventually found performance issues from too
much linear scanning. This was not obviously going to be a bottleneck
since our queues are usually of very small size, but ended up so.
The next type we considered was a LinkedHashSet, using the `head` and
`tail` methods to implement a dequeue-like operation and the set
operations being sufficient for the other operations. Unfortunately,
it seems that `tail` at present copies the entire queue despite not
seemingly needing to.

We moved to our own hand-crafted HashSet+Queue structure, but this PR
seems like it'd generally be beneficial for users of Vavr!
  • Loading branch information
j-baker authored and pivovarit committed Aug 19, 2024
1 parent 6ac4287 commit 86d1bf3
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion vavr/src/main/java/io/vavr/collection/LinkedHashMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ public LinkedHashMap<K, V> tail() {
if (isEmpty()) {
throw new UnsupportedOperationException("tail of empty LinkedHashMap");
} else {
return LinkedHashMap.ofEntries(list.tail());
return wrap(list.tail(), map.remove(list.head()._1()));
}
}

Expand Down

0 comments on commit 86d1bf3

Please # to comment.