Dart DoubleLinkedQueueEntry
last modified October 18, 2026
In this article, we show how to work with DoubleLinkedQueueEntry
in Dart. It represents a single element of a DoubleLinkedQueue and
is defined in the dart:collection library.
A DoubleLinkedQueue is a doubly linked list. Each node holds one
element and links to the previous and the next node. A
DoubleLinkedQueueEntry is a handle to such a node. Through the
handle we can read or replace the element, step to the neighbouring entries, and
insert or remove elements at that exact position in constant time, without
searching for an index.
The queue gives out entries with the firstEntry,
lastEntry and forEachEntry methods. The entry API is
small:
element- the element stored in the entry; it can be read and assigned.nextEntry()andpreviousEntry()- the neighbouring entries, ornullat either end of the queue.append(e)- inserts a new element right after this entry.prepend(e)- inserts a new element right before this entry.remove()- removes the entry from the queue and returns its element.
The class has no public constructor; entries are always obtained from a queue. The examples were run with Dart 3.13.
Navigating between entries
The first example gets the first entry of a queue and walks to its neighbours.
import 'dart:collection';
void main() {
var queue = DoubleLinkedQueue<String>();
queue.add('Apple');
queue.add('Banana');
queue.add('Cherry');
var first = queue.firstEntry()!;
print('First: ${first.element}');
var second = first.nextEntry()!;
print('Second: ${second.element}');
var back = second.previousEntry()!;
print('Back to first: ${back.element}');
print('Before the first: ${first.previousEntry()}');
print('Same entry: ${identical(first, back)}');
}
The firstEntry method returns null for an empty queue,
so its result is nullable; we assert it with ! because the queue
has three elements. The value of an entry is available in its
element property. The nextEntry and
previousEntry methods return entries of the same queue; moving
forward and then back gives the very same object. The first entry has no
previous entry, so previousEntry returns null.
$ dart main.dart First: Apple Second: Banana Back to first: Apple Before the first: null Same entry: true
Inserting elements around an entry
The prepend and append methods insert a new element
relative to an existing entry.
import 'dart:collection';
void main() {
var queue = DoubleLinkedQueue<String>();
queue.addAll(['Apple', 'Cherry']);
var first = queue.firstEntry()!;
first.prepend('Apricot');
first.append('Banana');
print(queue);
}
We insert Apricot before the entry holding Apple and
Banana right after it. No index is involved and the other elements
are not moved; only the links of the neighbouring nodes change. Both methods
take an element, not an entry, and return nothing.
$ dart main.dart
{Apricot, Apple, Banana, Cherry}
Removing an entry
An entry can remove itself from the queue.
import 'dart:collection';
void main() {
var queue = DoubleLinkedQueue<String>();
queue.addAll(['Apple', 'Banana', 'Cherry', 'Date']);
var second = queue.firstEntry()!.nextEntry()!;
var removed = second.remove();
print('Removed: $removed');
print('Queue: $queue');
print('Next of Apple: ${queue.firstEntry()!.nextEntry()!.element}');
}
The remove method unlinks the entry from the queue and returns the
element it held. The neighbours are linked together, so the entry that held
Apple now continues with Cherry.
$ dart main.dart
Removed: Banana
Queue: {Apple, Cherry, Date}
Next of Apple: Cherry
Traversing a queue
Following the links, we can traverse the queue in both directions.
import 'dart:collection';
void main() {
var queue = DoubleLinkedQueue<int>();
queue.addAll([10, 20, 30, 40, 50]);
print('Forward:');
var entry = queue.firstEntry();
while (entry != null) {
print(entry.element);
entry = entry.nextEntry();
}
print('Backward:');
entry = queue.lastEntry();
while (entry != null) {
print(entry.element);
entry = entry.previousEntry();
}
}
The forward loop starts at firstEntry and follows
nextEntry until it reaches null. The backward loop
starts at lastEntry and follows previousEntry.
Because a variable of a nullable type is promoted to a non-nullable one inside
the while condition, we can use entry.element directly.
$ dart main.dart Forward: 10 20 30 40 50 Backward: 50 40 30 20 10
Modifying a queue with forEachEntry
The forEachEntry method calls a function with each entry of the
queue. It is the safe way to change elements or remove some of them while
iterating.
import 'dart:collection';
void main() {
var queue = DoubleLinkedQueue<int>();
queue.addAll([1, 2, 3, 4, 5, 6]);
queue.forEachEntry((entry) {
if (entry.element.isEven) {
entry.element *= 10;
} else if (entry.element == 5) {
entry.remove();
}
});
print(queue);
}
The element property is assignable, so we multiply the even
elements by ten in place. The entry holding the value 5 removes itself during
the iteration. This works because the entries are the nodes of the queue and
forEachEntry remembers the next node before it calls our function.
Removing elements from a queue while iterating it with a for loop
would throw a ConcurrentModificationError.
$ dart main.dart
{1, 20, 3, 40, 60}
Moving and swapping elements
Entries make it easy to rearrange elements.
import 'dart:collection';
void main() {
var queue = DoubleLinkedQueue<String>();
queue.addAll(['A', 'B', 'C', 'D', 'E']);
// move the middle element to the front
var middle = queue.firstEntry()!.nextEntry()!.nextEntry()!;
var value = middle.remove();
queue.addFirst(value);
print('Moved to front: $queue');
// swap the first and the last element in place
var first = queue.firstEntry()!;
var last = queue.lastEntry()!;
var tmp = first.element;
first.element = last.element;
last.element = tmp;
print('Swapped ends: $queue');
// an entry is detached once it has been removed
print('Detached: ${middle.nextEntry()}');
}
First we take the third entry out of the queue with remove and put
its element at the front with addFirst. Then we swap the elements
of the first and last entries by assigning to element; the entries
stay in place and only the stored values change. Finally, we ask a removed entry
for its neighbour. A removed entry is detached from the queue, and
nextEntry returns null for it.
$ dart main.dart
Moved to front: {C, A, B, D, E}
Swapped ends: {E, A, B, D, C}
Detached: null
Best practices
- Null safety:
firstEntry,lastEntry,nextEntryandpreviousEntrycan returnnull; check before you use the result. - Keep entries only while needed: an entry is valid only while
it is in the queue. After
removeit no longer belongs to the queue. - Use entries for local edits:
append,prependandremoveare O(1) on an entry you already hold. Reaching an entry by walking from the end is O(n). - Do not change the queue in a for loop: use
forEachEntryorremoveWhereinstead. - Prefer plain queue methods such as
add,addFirstandremoveFirstwhen you do not need positional access.
Source
Dart DoubleLinkedQueueEntry documentation
We have shown how to navigate, insert, remove and modify elements of a
DoubleLinkedQueue through DoubleLinkedQueueEntry.
Author
List all Dart tutorials.