Repository navigation
Typos and small errors in "The Collections Framework" tutorials ( https://dev.java/learn/api/collections-framework/ ) #206
Description
Hello dev.java team!
Thanks so much for all this excellent content.
Just reporting some typos, some possibly outdated content, and some small errors (primarily in the "Storing Elements in Stacks and Queues" article, reported at the bottom of this issue comment).
In "Iterating over the Elements of a Collection", https://dev.java/learn/api/collections-framework/iterating/ , (archived as is at https://web.archive.org/web/20260305204909/https://dev.java/learn/api/collections-framework/iterating/ ),
The Iterable/Iterator implementations (both the record and "plain class" approaches presented) appear to have possible small issues
- the limit of the
hasNext()is not consistent with thenext()(whenhasNext()returns false, there is still another element to be returned bynext(), see below) - where one could simply write
return index++;to get-and-increment, an unnecessary secondary variable is used
record Range(int start, int end) implements Iterable<Integer> {
@Override
public Iterator<Integer> iterator() {
return new Iterator<>() {
private int index = start;
@Override
public boolean hasNext() {
return index < end; // hasNext() uses a half-open end excluded interval
}
@Override
public Integer next() {
if (index > end) { // next() uses a closed end included interval, should be >= to be consistent; next() can go one further after hasNext() returns false here
throw new NoSuchElementException("" + index);
}
int currentIndex = index;
index++;
return currentIndex; // maybe could just `return index++;` for desired get-and-increment behavior
}
The inconsistency of where next() stops returning elements and how hasNext() is defined can be demonstrated as follows:
jshell> Range r = new Range(0, 3);
r ==> Range[start=0, end=3]
jshell> var rIter = r.iterator();
rIter ==> Range$1@ff5b51f
jshell> rIter.next();
$4 ==> 0
jshell> rIter.next();
$5 ==> 1
jshell> rIter.next();
$6 ==> 2
jshell> // here the hasNext will start saying false, since they wrote hasNext in a half-open end excluded limi
t
jshell> rIter.hasNext();
$7 ==> false
jshell> // but the next() method supports up to including the limit, so it does have a next element
jshell> rIter.next();
$8 ==> 3
jshell> rIter.hasNext(); // still false
$9 ==> false
jshell> rIter.next(); // now will fail
| Exception java.util.NoSuchElementException: 4
| at Range$1.next (#1:16)
| at Range$1.next (#1:5)
| at (#10:1)
If you compare that to the default List iterator implementations, that is not the behavior (hasNext() usually returns false only if the next call to next() will throw NoSuchElementException).
The same issues also occur in the "plain class" example that follows.
- Separately, there appears to be a typo on the line:
for (int i : new Range1(0, 5)) {
in that "Range1" is written when "Range" seems intended.
In the Table of Contents for this tutorial, https://dev.java/learn/api/collections-framework/ (archived as is: https://web.archive.org/web/20260305180836/https://dev.java/learn/api/collections-framework/ ):
- "Why Choosing a Collection over an Array?" should be "Why Choose a Collection over an Array?"
- "Using a Collection to Store and Retrieve Elements" is missing a period at the end
In "Storing Data Using the Collections Framework", https://dev.java/learn/api/collections-framework/intro/ (archived as is at: https://web.archive.org/web/20260305183418/https://dev.java/learn/api/collections-framework/intro/ ):
- The sentence "Is what you need consists in:", I think a different sentence is intended, beginning with "If" instead of "Is"
In "Getting to Know the Collection Hierarchy", https://dev.java/learn/api/collections-framework/organization/
(archived as is https://web.archive.org/web/20260305191553/https://dev.java/learn/api/collections-framework/organization/ ):
-
FYI, this article is not updated yet for the new SequencedCollection, SequencedSet interfaces released in Java SE 21 yet (see https://docs.oracle.com/en/java/javase/21/core/creating-sequenced-collections-sets-and-maps.html for reference, https://web.archive.org/web/20260305192949/https://docs.oracle.com/en/java/javase/21/core/creating-sequenced-collections-sets-and-maps.html )
-
In the sentence, "It adds several vey useful operations on SortedSet, among them the possibility to iterate over the elements in the descending order", "vey" should be "very"
-
In the sentence, "You will see more details ont that later", "ont" should be "on"
In "Storing Elements in a Collection", https://dev.java/learn/api/collections-framework/collection-interface/ (archived as is: https://web.archive.org/web/20260305200446/https://dev.java/learn/api/collections-framework/collection-interface/ ):
- In the sentence, "You will see more discussions on the right implementation to choose in later in this tutorial",
"to choose in later in this tutorial" should be "to choose later in this tutorial" (remove extra "in").
In "Creating and Processing Data with the Collections Factory Methods", https://dev.java/learn/api/collections-framework/immutable-collections/ (archived as is at https://web.archive.org/web/20260305231534/https://dev.java/learn/api/collections-framework/immutable-collections/ ):
-
In the sentence, "The Collections Framework comes with another factory class: Collections, with a set of method to manipulate collections and their content."
"with a set of method" should be "with a set of methods" -
In the sentence, "The Java Util Concurrent framework has better solutions to offer", "Java Util Concurrent" might be intended to say "The java.util.concurrent package has better solutions to offer" ( https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/concurrent/package-summary.html ).
In "Storing Elements in Stacks and Queues", https://dev.java/learn/api/collections-framework/stacks-queues/ (archived as is at https://web.archive.org/web/20260305234616/https://dev.java/learn/api/collections-framework/stacks-queues/ ):
- re: in the table "Modeling FIFO Queues with Queue",
it is written that the "Behavior when the queue is full or empty" for the operation "poll" is "returns false",
which is not correct and should be "returns null" (like peek), see
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Queue.html#poll() .
- re: the text block on Deque methods:
Moreover, Deque also defines the methods you would expect in any queue or stack class:
push(element): adds the given element to the head of the double ended queue
pop(): removes and return the element at the head of the double ended queue
poll(): does the same at the tail of the double ended queue
peek(): shows you the element at the tail of the double ended queue.
The sentences on Deque poll and peek behavior appear incorrect,
e.g., "poll(): does the same at the tail of the double ended queue", appears to be mistaken in that poll removes from the head, not the tail as written.
Compare this to the official documentation, https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Deque.html#poll()
which says
Retrieves and removes the head of the queue represented by this deque (in other words, the first element of this deque), or returns null if this deque is empty.
This method is equivalent to pollFirst().
The same error occurs for peek, as peek also shows the element at the head, not the tail of the Deque (see https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Deque.html#peek() ).
-
The sentence "In case there is no element to pop, poll, or peek, then a null value is returned by these methods."
appears mistaken as pop throws NoSuchElementException when the Deque is empty (see https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Deque.html#pop() ). -
The sentence "There is one difference though: the peek operations are named getFirst() and getLast() in Deque, and element() in Queue."
seems confusing as "peek" is available in Deque and Queue (as well as the equivalent peekFirst() and also a peekLast()), whereas this sentence suggests they are not.
There are also the mentioned getFirst()/getLast() in Deque and element() in Queue that also return elements without removing them but which throw NoSuchElementException instead of returning null on empty Deques or Queues.
Finally, this may not be an error, but I think is worth reviewing:
Near the beginning of this article, it is written of stacks and queues that:
These structures are very simple and gives you three main operations.
push(element): adds an element to the queue, or the stack
pop(): removes an element from the stack, that is, the youngest element added
poll(): removes an element from the queue, that is, the oldest element added
peek(): allows you to see the element you will get with a pop() or a poll(), but without removing it from the queue of the stack.
In this explanation, the sentence "push(element): adds an element to the queue, or the stack" might be confusing as the Queue interface actually only includes "add" and "offer" for adding to the queue , NOT push, which comes from the stack interface ( see https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Queue.html ).
From Java 25 SE documentation, Queues have:
Summary of Queue methods
Throws exception Returns special value
Insert add(e) offer(e)
Remove remove() poll()
Examine element() peek()
and Stacks have push, pop, and peek ( https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Stack.html ).
The article does discuss this later, defining push operations for a queue as add and offer, but I think "push(element)" in reference to a queue might be better immediately paired with a clarifying statement that "add" or "offer" are the actual method names, not "push" for a queue.
Depending on available time I may add additional items here as I am still reviewing this series of artices so feel free to leave open even if you address the above (I would also be happy to confirm any changes before closing if desired).
Thanks very much!
Activity
JosePaumard commentedon Mar 6, 2026
Thank you again for your reports! I just pushed fixes.
The upper bound of the Range class is indeed excluded. I added that in a comment.
The idea of the section on Queues and Statcks is to first define the basic operations (they do not depend on the language or API you are using), then show the implementations. Indeed, there is no "simple" implementation of the concept of queue nor stack, and the Stack class is an old legacy class that you should not use. Confusion comes from this old class, and from the fact that there is no simple, basic implementation of these concepts.
I still need to update the CF structure with SequencedCollections. I keep that in mind, and will do that a little later.
willy-b commentedon Mar 8, 2026
Thanks Jose!
Re: your live-site updates above for "The Collections Framework" pages (feel free alternatively to send PRs for review as it may be easier for me to check, but otherwise I am happy to keep reviewing this way using web.archive.org to compare)
For "Storing Elements in Stacks and Queues", https://dev.java/learn/api/collections-framework/stacks-queues/ (archived as is at https://web.archive.org/web/20260307235916/https://dev.java/learn/api/collections-framework/stacks-queues/ , vs old version at https://web.archive.org/web/20260305234616/https://dev.java/learn/api/collections-framework/stacks-queues/ ):
still appears mistaken as pop throws NoSuchElementException when the Deque is empty (see https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Deque.html#pop() ).
And as stated above but I think it also slipped through the cracks,
seems confusing as "peek" is available in Deque and Queue (as well as the equivalent peekFirst() and also a peekLast()), whereas this sentence suggests they are not.
There are also the mentioned getFirst()/getLast() in Deque and element() in Queue that also return elements without removing them but which throw NoSuchElementException instead of returning null on empty Deques or Queues.
For https://dev.java/learn/api/collections-framework/iterating/ after your change above, archived at https://web.archive.org/web/20260306182646/https://dev.java/learn/api/collections-framework/iterating/ (vs old version https://web.archive.org/web/20260305204909/https://dev.java/learn/api/collections-framework/iterating/ ):
The next() vs hasNext() discrepancy was acknowledged and fixed for the record Iterable, but the next example of a "plain class" solution, has not been fixed yet; the
next()method in the Iterator of the non-recordclass Range implements Iterable<Integer>snippet needs the same update to throw an NoSuchElementException ifindex >= endinnext()to be consistent withhasNext()mentioned earlier but not updated or commented on in your response above: both the
record Rangeand the "plain class"class Rangesnippets should probably justreturn index++;innext()instead of introducing a secondary variable to hold and return the current index before incrementingthe class name
Range1in one of the snippets (see below) is not defined and appears a typo whereRangewas intended (reported above but was not fixed in your last update):In the Table of Contents for this tutorial, https://dev.java/learn/api/collections-framework/ (archived as is: https://web.archive.org/web/20260307234704/https://dev.java/learn/api/collections-framework/ , vs old https://web.archive.org/web/20260305180836/https://dev.java/learn/api/collections-framework/ ):
is not fixed or commented upon yet.
In "Getting to Know the Collection Hierarchy", https://dev.java/learn/api/collections-framework/organization/
(archived as is https://web.archive.org/web/20260307235117/https://dev.java/learn/api/collections-framework/organization/ , old version: https://web.archive.org/web/20260305191553/https://dev.java/learn/api/collections-framework/organization/ ):
Not fixed yet:
Once these already reported items in these articles are confirmed fixed, if it is ok with you, I will submit additional discovered items in this issue (I am preparing them presently separately).
Thanks again!
JosePaumard commentedon Mar 9, 2026
Thank you again for all this! I just pushed a fix.
As for the methods of Deque: I fixed and added some elements. I prefer to keep separated the methods xxxFirst() and xxxLast() as I think that it's easier to remember the structured of this API in that way. The push pop poll peek methods are also there, and I added the behavior when the deque is full or empty.
As for the index++. People often get confused about the ++ really been executed or not. Some speakers even do nice quiz with that ;) So even if it can be written in the way you suggest, I prefer to keep it explicit. Don't worry, the JVM will fix this at runtime.
willy-b commentedon Apr 12, 2026
Thanks for fixing most of the items reported!
However, it looks like one different small error might have come in with your team's last set of updates to https://dev.java/learn/api/collections-framework/stacks-queues/ .
Re: #206 (comment)
I had written:
In https://web.archive.org/web/20260411212316/https://dev.java/learn/api/collections-framework/stacks-queues/
The sentence has been updated by your team to:
Which is unfortunately not quite correct (I asked to update "pop" to note it throws NoSuchElementException instead of null, not to say "peek" or "poll" throw that Exception, which they don't),
and is also inconsistent with the immediately preceding sentences:
(noting in passing also that in "This method return null if there is no element to poll." in "poll()"'s description , "return" should be "returns")
The sentence might be rewritten:
(or something similar, making clear pop throws a NoSuchElementException, but peek and poll return null when there are no elements remaining)
I am reviewing https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ presently (and working through the JMH benchmarks described) (article archived as is at https://web.archive.org/web/20260411221339/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ ).
So far I can report the following:
In the sentence:
"there is not" should be "there are not"
"between both" might be better as "between them"
Re:
LinkedList is not an interface, so this seems inaccurate. Maybe this should be rewritten to say something like "Despite the shared interface, List, these implementations, LinkedList and ArrayList are not working in the same way, at all".
Re:
"that it" in "that it much faster" should be "that is"
The description of the speed difference, FOR ARRAYLIST, between the index and the for-each Iterator seems somewhat inconsistent here. First it is said "both patterns are roughly the same", noting "an index is a little more costly", but then it is said that using the for-each results in "code that it [sic] much faster"; perhaps it should say "that is faster" rather than "much faster" (indeed, it is a small advantage to iterate over indexing when using ArrayList compared to the advantage of iterating for a LinkedList which is tremendous).
Re:
The article does not mention any logarithmic time [e.g. O(log(n))=O(ln(n))] operations offered specifically by the List interface ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/List.html ) itself, so I think that complexity class should have an example provided from this interface or the mention should be considered to be removed from this sentence.
Outside of the List interface itself, there are many examples, like Collections.binarySearch which accepts any (already SORTED) List and for RandomAccess lists with constant-time random access (like ArrayList) runs in logarithmic time (O(log(n)) = O(ln(n)) (e.g. in OpenJDK
Collections.binarySearch(List<? extends Comparable<? super T>> list, T key), https://github.com/openjdk/jdk/blob/1e2b0d2b67c7ae0843c9adbc641471040fbe7d71/src/java.base/share/classes/java/util/Collections.java#L216 ),but binary search is not part of the List interface, nor do ArrayList's indexOf/contains implementations use any tricks on sorted or nearly sorted lists, and use a simple O(n) linear search from the head to the tail of the List looking for the object ( https://github.com/openjdk/jdk/blob/1e2b0d2b67c7ae0843c9adbc641471040fbe7d71/src/java.base/share/classes/java/util/ArrayList.java#L287 , https://github.com/openjdk/jdk/blob/1e2b0d2b67c7ae0843c9adbc641471040fbe7d71/src/java.base/share/classes/java/util/ArrayList.java#L299 , https://github.com/openjdk/jdk/blob/1e2b0d2b67c7ae0843c9adbc641471040fbe7d71/src/java.base/share/classes/java/util/ArrayList.java#L276 ).
Sort is O(n log (n)) (or at least O(n) if passed an already sorted list or nearly sorted list with a constant number of unsorted elements as it takes O(n) to even check if the list is sorted, and smart sorting implementations do take advantage of this but this is still slower than logarithmic) and lists are not assumed to be sorted in the List interface.
PriorityQueue ( https://github.com/openjdk/jdk/blob/1e2b0d2b67c7ae0843c9adbc641471040fbe7d71/src/java.base/share/classes/java/util/PriorityQueue.java#L72 ) does NOT implement List (and I am not aware of any Heap-like or alternatively Tree-like data structures which do implement List ), so available List implementations add/remove (and get/set), as far as I am aware, in either O(1) or O(n) time (e.g. see a description of ArrayList time complexities in OpenJDK at https://github.com/openjdk/jdk/blob/1e2b0d2b67c7ae0843c9adbc641471040fbe7d71/src/java.base/share/classes/java/util/ArrayList.java#L42-L48), NOT O(log(n)).
There are many logarithmic time operations possible on Lists in special cases (like binary search on pre-sorted constant-time RandomAccess Lists) but what operations offered by the List interface itself run in logarithmic time on a Java API implementation is a different question.
I will report back with more feedback if I find anything after reproducing the JMH benchmarks in https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ and reviewing the whole article.
Thanks so much!
JosePaumard commentedon Apr 13, 2026
Thank you again for your report! I just pushed a fix.
This section focuses on the differences between ArrayList and LinkedList, and show that algorithm complexity is not always relevent when it comes to comparing performance of classical list operations.
So, even if the last part of your comment is very interesting, I prefer to keep it for later, and in another section. BTW there are also interactions with the Vector API, which can be used internally, that would make such a section even more interesting.
BTW, there is one part of your comment that I'm not sure to understand?
willy-b commentedon Apr 14, 2026
Thanks so much for the additional fixes!
In https://web.archive.org/web/20260413140310/https://dev.java/learn/api/collections-framework/stacks-queues/
vs https://web.archive.org/web/20260411212316/https://dev.java/learn/api/collections-framework/stacks-queues/ :
has been removed by you and this is fine since it is redundant with preceding sentences anyway. Thanks!
In https://web.archive.org/web/20260413142128/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ vs old version https://web.archive.org/web/20260411221339/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/:
has been updated by you to "The LinkedList class and the ArrayList class both implement the List interface, but their implementations are different". Thanks!
Here are possible additional issues I found in https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ (archived as is at https://web.archive.org/web/20260413142128/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ ):
Re:
When discussing timings in the section "Iterating with an Index and an Iterator" of https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ (archived as is at https://web.archive.org/web/20260413142128/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ )
Re dev.java author's statement on LinkedList 1000 element iteration times on their computer (must be compared relative to other timings reported by them throughout the article, hard to absolutely compare without specs):
The ratio between the two measurements shows the expected slowdown for iterating using an index vs using an iterator (bad algorithm for LinkedList). But the 4 milliseconds with an iterator for a LinkedList of length 1000 is much too slow given the around 1 nanosecond times to read first/last and around half a microsecond times to iterate to middle reported elsewhere in the article.
I think there might be an error here in terms of units. I think this is potentially based on an error of writing microsecond/op (μs/op with a "mu" not "m") as "ms/op" read as milliseconds/op for the time for iterating over the entire 1000 elements and should be instead,
(Saying "5 microseconds with an iterator" to also adjust for the observation that 4.950μs should be rounded to 5μs not 4μs)
Recall the earlier tables showing the timings to read to the middle element of an ArrayList or LinkedList using an iterator showing constant time O(1) for ArrayList and linear time O(n) for LinkedList:
Those are nanosecond timings. (If "ns" weren't enough to conclude these are nanoseconds, see the sentence "This difference is very small, a fraction of a nanosecond, and not really relevant though" below one of the tables using "ns/op".)
The table above says iterating to the middle of a 1000 element LinkedList takes 566.079 nanoseconds (roughly half a microsecond) on that author's machine.
Assuming those are correct, it seems we should expect reading 1000 elements in a LinkedList (using an iterator, not indexing) to take much closer to 2x this read-to-middle number (or around 1100 nanoseconds or 1.1 microseconds) than to 2,000x this number or 1.1 milliseconds (or 4 milliseconds as quoted above, which I believe was intended to be 4 microseconds).
Again, we can check another table provided by this author,
showing the constant time O(1) for reading the first element of either ArrayLists or LinkedLists, and confirm the O(1) single operation time on the article's author's machine was around a nanosecond:
So we expect iterating using an iterator (O(n)) through either the LinkedList or ArrayList to take closer to 1000x the single operation number, or a microsecond, than to 1,000,000x this amount or a millisecond (no reason for a high constant multiplier in this case), as iterating in both cases is O(n) without a large constant (it is true that iterating using indexing instead of an iterator for LinkedList is O(n^2) and we will see indexing vs using an iterator for a LinkedList is indeed ~120x slower, even after fixing the units). Indeed, on my own 4GHz CPU machine, I see nanoseconds for single operations and microseconds for using iterators to go through length 1000 lists (of both LinkedLists and ArrayLists), and hundreds of microseconds to do the slow O(n^2) index iteration of the LinkedList.
The ArrayList table for the "Iterating with an Index and an Iterator" section also seems to have the same issue for both types of lists writing "ms/op" instead of "microsecond/op" or "μs/op" (with a "mu" (μ) not "m")
**Here it is even more obvious (recall ArrayList read first AND read to middle times were both given as around a nanosecond) as we don't expect any slowdown for any type of looping on ArrayList (unlike LinkedList which has the switch from O(n) to O(n^2) when using an index to iterate instead of an iterator), so these times to loop through 1000 element ArrayLists should be roughly 1000x the single element read times, or 1,000x 1 nanosecond, which is 1 microsecond, not 1 millisecond.
Repeating for clarity: I think the units in these tables and the sentence quoted above, ms, are written as milliseconds / op but should all be microseconds/op (μs/op).
Furthermore it should be clarified that iterating through all 1000 elements is considered the single operation (unless it is not intended to be but otherwise not clear why we are stepping up from nanoseconds to a higher unit).
The unit change seems required to be consistent with nanosecond timings for access 1st, last, middle, etc in earlier sections and consistent with general order of magnitude processor speeds expected these days, gigahertz.
As a double check assuming gigahertz processors, we would expect timings in the microseconds (not milliseconds) for even 1000 iterations as following a reference in a LinkedList to the next node (moving to the adjacent index in an ArrayList) and accessing the referenced Integer should not take thousands or tens of thousands of processor cycles. Taking 4ms as quoted in the article to loop through all elements in a 1000 element LinkedList using an Iterator means taking 1/250 of a second so for e.g. a 2GHz processor that is 8 million cycles to iterate through e.g. a LinkedList of length 1000 or 8000 cycles per node, i.e. 8000 cycles to follow the reference from 1 LinkedList node to the next, which does not seem right.
This also applies to:
(units here, ms, are again written as milliseconds / op but I suspect should be microseconds/op (μs/op))
On "Analyzing the Memory Consumption of LinkedList and ArrayList" of https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ (archived as is at https://web.archive.org/web/20260413142128/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ )
Re:
List.of(1)produces a 26 byte footprint (excluding the Integer and the shared dummy Object reference used by the underlying implementation class List12 when there is only one element in recent versions of Java)? The memory footprint of these objects are highly configuration dependent (compression on/off for references, compression on/off for class pointers, since Java 25's https://openjdk.org/jeps/519 the-XX:+UseCompactObjectHeadersflag, 32 bit vs 64 bit VM mode, etc).Note my JVM is configured (matches default shown on JOL tool website) (NOT using CompactObjectHeaders):
But as mentioned above there are many other configurations possible, however I didn't see any obvious combination of these that gives 26 bytes for
List.of(1)(I see 28 bytes fromList.of(1)in most configurations and it appears based on later memory numbers given, e.g. in the final table comparing ArrayList of size 2, Linked List, Default ArrayList, Default trimmed ArrayList as elements are added one by one that the author is also using "Object alignment: 8 bytes" which should make 26 bytes impossible.)I agree, I see 80 bytes in this case (see further down for full detail).
But the 80 bytes number given above is inconsistent with the table shown a bit later, which says 76 bytes WITHOUT trimToSize() (my comments in square brackets):
Given the 8 byte alignment suggested by the last table in the article (same as used on my system and in JOL documentation), I don't know how 76 bytes comes up.
Here is how my system gets to 80 bytes for an ArrayList with capacity 10 and 1 Integer in it, excluding the Integer:
Another possible discrepancy is,
the first memory consumption table shows for a trimmed ArrayList with 1 element 44 bytes:
But there is another table with a "Default trimmed ArrayList" comparison column further down,
showing the size of an ArrayList after adding N elements and calling trimToSize(), and in
that table we see 48 bytes for 1 element (first column is number of elements added):
I see exactly what he has in this later table, 40 bytes for an empty ArrayList (set to capacity 0), and 48 bytes for an ArrayList of capacity 1 (whether by calling trimToSize() or initializing it to that capacity),
not the 44 bytes shown in the preceding table for "(after trimToSize())" with 1 element. Can we double check the 44 bytes or explain the difference in configuration?
For an ArrayList with 1 Integer element after trim to size I see, 48 bytes (64 bytes including 16 bytes for the Integer, or 48 bytes without), would be 44 without alignment bytes, getting 4 bytes added for Object[1] array base offset 16 plus 4 bytes is 20 bytes, adds 4 to align with 24:
Matching the 2nd table in the article, not the 1st, but maybe in the 1st table he left off the 4 bytes added to the raw 20 bytes required by the elementData ([Ljava.lang.Object;) for "Object alignment: 8 bytes" though that seems enforced in the 2nd table?
Thanks!
JosePaumard commentedon Apr 15, 2026
Thank you Willy, espcially for your work on the memory part.
Fortunately, this section starts with the following: "as different JVM may handle memory differently, and a single JVM can have different strategies depending on the amount of memory it is running in.". And it's even worse if you add the 32 bits / 64 bits differences to the lot. All the numbers have been carefully been reviewed by Stuart Marks, who wrote List.of() among (many) other things. I think the main idea of this section is: "if memory is an issue for you, be careful, and measure your consumption carefully, in your own production environment".
JosePaumard commentedon Apr 15, 2026
As for the benchmarks, indeed these are microseconds and not milliseconds. I just pushed a fix.
Again, thank you!
willy-b commentedon Apr 15, 2026
Excellent!
(Though a couple of small items remain even dismissing the few concerns in the last comment about possible inconsistencies in a couple of places on memory numbers (which are definitely highly configuration dependent).)
I can confirm in the latest version https://web.archive.org/web/20260415205036/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ vs the previous https://web.archive.org/web/20260413142128/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ :
Typos reported earlier were fixed
"more expensive that" should be "more expensive than" [fixed]
"executed on a hardware" should be "executed on hardware" [fixed]
"consume" should be "consumes" [fixed]
The LinkedList iterator vs index times for iterating though 1000 elements have had the units updated (you are using "us" instead of "μs" but I believe it will be clear in context now that text has been updated to "half a millisecond" and "4 microseconds":
Nit: 4.950 rounds to 5, so "5 microseconds" would better match the table value (4.950 μs) unless you want the floor of the average rather than the closest whole number to the average.
(Note another typo I had not reported yet remains near here:
In the sentence
"This has an impact on any reference based data structure: linked list of course, but also trie trees, binary trees, read black trees, skip lists, and to a lesser extent, hash maps."
I suspect "read black trees" should be "red black trees".)
However, the units for the ArrayList iterator numbers for a 1000 element ArrayList are not fixed yet:
Thanks very much!
JosePaumard commentedon Apr 16, 2026
As for the us vs. \mu s, this is the convention used when the mu letter is not available, which is often the case with fixed sized fonts.
As for what should be written 584.889 ± 4.396 us/op. This is what JMH gives, so I prefer to keep it that way. Clearly, it should probably written 585 ± 5, meaning that the result is probably between 570 and 600. But that's a discussion for somewhere else ;)
Again, thank you for your report! I just pushed a fix for the rest.
willy-b commentedon Apr 19, 2026
Thanks!
In the latest version of the Table of Contents for this series https://dev.java/learn/api/collections-framework/ (archived as is at https://web.archive.org/web/20260418234821/https://dev.java/learn/api/collections-framework/ ):
"Sortedmap" should be "SortedMap".
In the latest version of https://dev.java/learn/api/collections-framework/intro/ (archived as is at https://web.archive.org/web/20260418235025/https://dev.java/learn/api/collections-framework/intro/ ):
"a set of interfaces that models different way of storing data" should be "a set of interfaces that models different ways of storing data" with "ways" instead of "way".
It may be worth using add and remove, or offer and poll, instead of push and pop when describing a queue as those verbs are usually used with a stack or deque.
In fact, there are no methods named push and pop on the Queue interface ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Queue.html ),
though they are present on Stack (class), Deque (interface), and LinkedList (class; often used for Queues but also Stacks) for example. (This is occurring in a different sentence and context than the place I previously brought this up which was at least comparing queues and stacks so may make more sense in other case to try to share terms than here.)
"bother learn" should be "bother to learn" or "bother learning".
In the latest version of https://dev.java/learn/api/collections-framework/organization/ (archived as is at https://web.archive.org/web/20260418235404/https://dev.java/learn/api/collections-framework/organization/ ):
"do someting" should be "do something".
This is a little simplified in that since Java 21, List now includes addFirst and addLast, so one can add to the head of the List so the last element added by addFirst will be the first in the encounter order (LIFO instead of FIFO behavior is possible with addFirst instead of add/addLast) of the associated iterator for for-each loops or first index in get(0) etc.
In the latest version of https://dev.java/learn/api/collections-framework/collection-interface/ (archived as is at https://web.archive.org/web/20260418235121/https://dev.java/learn/api/collections-framework/collection-interface/ ):
While it is true that Collection.add only allows returning false for items rejected as duplicates, which doesn't happen with List, and that if the method returns List will return true, it is not true that "it should not fail for a List", as per the spec https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/List.html#add(E)
it is just that instead of returning false, Exceptions are used, e.g.:
While it is true there is no compile-time error to call Collection.contains(o) where o instanceof T == false,
per the Collection specification ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Collection.html#optional-restrictions ) Exceptions can be thrown:
"first" should be "the first" and "cell" should be "cells".
In the latest version of https://dev.java/learn/api/collections-framework/lists/ (archived as is at https://web.archive.org/web/20260418235516/https://dev.java/learn/api/collections-framework/lists/ ):
"work" should be "works".
In the latest version of https://dev.java/learn/api/collections-framework/sets/ (archived as is in
https://web.archive.org/web/20260418235725/https://dev.java/learn/api/collections-framework/sets/ ):
There is also ConcurrentSkipListSet ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/concurrent/ConcurrentSkipListSet.html ).
(Skip list data structures can be used in place of balanced tree data structures even outside the context of designing for concurrency but ConcurrentSkipListSet is the SortedSet supported by the Java API for concurrent applications.)
might be clearer if the descriptions were in the same order as the methods being described. "ceiling(element)" returns "the lowest element greater or equal [to] the provided element"
but "ceiling" comes before "floor" while its description comes after "floor"s description ("the greatest element lesser or equal [to]").
In the latest version https://dev.java/learn/api/collections-framework/maps/ (archived as is at
https://web.archive.org/web/20260419000052/https://dev.java/learn/api/collections-framework/maps/ ):
"application" should be "applications".
There is a missing period after value, and several other entries in the subsequent list after "This leads to several consequences for the content of the map.", "you can define the following operations on a map", "You can also define the classic, set-like operations:".
"on" should probably be "in".
In the latest version of https://dev.java/learn/api/collections-framework/working-with-keys-and-values/ (archived as is at https://web.archive.org/web/20260419000633/https://dev.java/learn/api/collections-framework/working-with-keys-and-values/ ):
"resut" should be "result".
In the latest version of https://dev.java/learn/api/collections-framework/maps-and-lambdas/ (archived as is at https://web.archive.org/web/20260419000654/https://dev.java/learn/api/collections-framework/maps-and-lambdas/ ):
First "existingValue" should probably renamed to be "oldValue" to match the documentation,
then "the existing value is replaced only if it matches the new value" should be "the current value is only replaced with he
newValueargument if the current value matches theoldValueargument" or something similar as the existing value in the map is not compared to henewValueargument (the check gating the update ismap.containsKey(key) && Objects.equals(map.get(key), oldValue))."beacause" should be "because".
In the latest version of https://dev.java/learn/api/collections-framework/sorted-maps/ (archived as is at https://web.archive.org/web/20260419000557/https://dev.java/learn/api/collections-framework/sorted-maps/ ):
Then in describing the NavigableMap interface below, it says:
That is,
firstKey(),lastKey()which are part of the SortedMap interface are introduced again in the subinterface NavigableMap (onlyfirstEntry(),lastEntry(), should be mentioned here; this article haspollFirstEntry(),pollLastEntry()in a separate section )which is unnecessary and contrary to the way that the documentation describes it (firstKey, lastKey are not mentioned as updated in any way unlike some other methods see https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/NavigableMap.html ).
In the latest version of https://dev.java/learn/api/collections-framework/choosing-keys/ (archived as is at https://web.archive.org/web/20260419000855/https://dev.java/learn/api/collections-framework/choosing-keys/ ):
"key" should be "keys".
Thanks very much!
JosePaumard commentedon Apr 20, 2026
Thank you again for your report! I just pushed a fix.
As for the Queue operations: the method names were chosen to avoid name collisions, but the operations are still push pop peek. So I prefer to keep in that way.
As for the List: operations that apply to the first or last element come from SequencedCollection. It turns out that List can trivialy have these operations, but there is still a difference between both.
As for the ConcurrentSkip structures, there are outside of the scope of this section. All these structures are super complex, and would require a section on their own to explain them. And using them outside of a concurrent environment would be a mistake.
And double checked that the fixes were pushed ;)
willy-b commentedon Apr 21, 2026
Thanks, I reply to your latest updates below.
No pressure from me to include me on any related pull requests (not all content on dev.java is even visible to me on GitHub as I am external to the project so I know that is not possible in all cases) but using those features may simplify the reviewing process; also at the end of the ticket I will go through and advise updating the "Last update" timestamps on all pages your team has pushed edits to (your team has not been updating "Last update" dates when modifying pages), but that is out of my control as I am not actually making edits on this project.
In the latest version of https://dev.java/learn/api/collections-framework/sets/ (archived as is at https://web.archive.org/web/20260420150334/https://dev.java/learn/api/collections-framework/sets/ ),
there has not been a fix since my last comment and review of the page (archived previously at https://web.archive.org/web/20260418235725/https://dev.java/learn/api/collections-framework/sets/ ).
I previously commented:
The above has not been updated in https://web.archive.org/web/20260420150334/https://dev.java/learn/api/collections-framework/sets/ vs https://web.archive.org/web/20260418235725/https://dev.java/learn/api/collections-framework/sets/ .
That is, the descriptions should be: [adding (A,B) and (1,2) labels to the parts to discuss the ordering afterwards]
(A) "ceiling(element)" returns (1) "the lowest element greater or equal [to] the provided element" (yes, "lowest" occurs in ceiling as it is lowest WHILE BEING greater than or equal to)
(B) "floor(element)" returns (2) "the greatest element lesser [than or] equal [to]" (yes, "greatest" occurs in floor as it is greatest WHILE BEING less than or equal to)
But the current sentence still has the ordering "(A) and (B) return (2) or (1)" instead of "(A) and (B) return (1) and (2), respectively". (Alternatively the order of ceiling and floor could be switched as in "(B) and (A) return (2) and (1), respectively" while keeping the order of descriptions.).
Re: https://dev.java/learn/api/collections-framework/maps-and-lambdas/ (archived as is at https://web.archive.org/web/20260420151449/https://dev.java/learn/api/collections-framework/maps-and-lambdas/ ),
I had commented on the previous version https://web.archive.org/web/20260419000654/https://dev.java/learn/api/collections-framework/maps-and-lambdas/ :
This has been updated in the latest to (archived as it is at https://web.archive.org/web/20260420151449/https://dev.java/learn/api/collections-framework/maps-and-lambdas/ ):
This is better but it says the "first argument" when it should be the "second argument" (out of 3, first is the key) or "first value argument" (as the 3 arguments are key, oldValue, newValue), and "existingValue" should probably still be renamed "oldValue" to match the official documentation.
Re: https://dev.java/learn/api/collections-framework/collection-interface/ (archived as it is now at https://web.archive.org/web/20260420150152/https://dev.java/learn/api/collections-framework/collection-interface/ )
I had commented on the previous version (archived at https://web.archive.org/web/20260418235121/https://dev.java/learn/api/collections-framework/collection-interface/ ), see last comment from me in this ticket, repeated here for clarity:
Now, in the latest version, https://web.archive.org/web/20260420150152/https://dev.java/learn/api/collections-framework/collection-interface/ ,
this has been updated to:
But this is not quite right.
Per the Oracle official javadoc: ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Collection.html#add(E) )
So "This method returns a boolean in case the operation failed" is not right. Implementations must throw an exception for most failures to add an element (all of those except where the element is already in the collection, as e.g. attempting to add a duplicate to a Set).
So maybe this could be updated to:
"add(element): adds an element in the collection. This method returns a boolean which is true if the collection changed as a result of the call (calling add on a Set which already contains the element would return false). If the call returns the collection MUST contain the specified element. Thus while collections may place other restrictions on elements added they must throw exceptions rather than return false if refusing to add an element for any reason other than that the collection already contains the element. For example, a specific List implementation may set restrictions on the elements it allows, for instance, it could choose to refuse nulls, but would refuse those with a NullPointerException instead of returning false."
Separately in https://web.archive.org/web/20260420150152/https://dev.java/learn/api/collections-framework/collection-interface/ ,
below
the following line has been added by your team to address one of my previous comments (that using contains with the wrong type can still fail but with an exception not a compile-time error):
Which is great and now just needs a period at the end (this version has no period after this sentence before the next text).
(There are still bulleted lists I commented on across pages in this tutorial that have inconsistent use of periods at the end of each bullet, but will not repeat that here as not likely to confuse anyone.)
Thanks!
23 remaining items
willy-b commentedon Jun 23, 2026
Thanks!
Re: above I had asked
and you just responded:
Thanks, but there are many places in the existing articles where hardware dependent recommendations in favor of ArrayList are made, e.g. (https://web.archive.org/web/20260622182311/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ )
but we are still not having the JDK documentation recommendation of ArrayDeque over LinkedList even for queues coming in (nor any mention of ArrayDeque as a circular array growing from the middle out meaning adding at the head as well as tail is very fast except infrequently when the array is resized but that is amortized by scaling by a factor), e.g. the page also says
When the JDK documentation says ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/ArrayDeque.html )
Feel free to disagree, but I do maintain it would be consistent with the current approach (and the JDK documentation) to recommend ArrayDeque on pages where it is not mentioned (it is already mentioned once on the page on ArrayList vs LinkedList, but not on https://dev.java/learn/api/collections-framework/lists/ (archived as is at https://web.archive.org/web/20260531223132/https://dev.java/learn/api/collections-framework/lists/ )) where it says that even for a queue a LinkedList is the best choice, directly contradicting the ArrayDeque documentation quoted above:
That aside, here's another round of items in this tutorial series found during additional review, thanks so much for considering whether to fix them!
In the latest version of https://dev.java/learn/api/collections-framework/maps-and-lambdas/ (archived as is at https://web.archive.org/web/20260622050455/https://dev.java/learn/api/collections-framework/maps-and-lambdas/ )
In the paragraph
The three methods mentioned are:
The second point of this description seems inaccurate: compute() and computeIfPresent() do not take as an argument "the value bound to that key".
What is true is that compute() and computeIfPresent() take a BiFunction as an argument, and that BiFunction takes a value as an argument, which is not the same thing.
So I would suggest "- the value bound to that key, in the case of compute() and computeIfPresent()" be removed.
It is already explained below the 3rd current point that for compute() and computeIfPresent() , the BiFunction passed as a 2nd argument to these methods, itself takes the mapped value for a given key as a 2nd argument (to the BiFunction).
Also in the above "or a mapping function in the case of computeIfAbsent()" should be "or a mapping Function in the case of computeIfAbsent()".
In the latest version of https://dev.java/learn/api/collections-framework/collection-interface/ (archived as is at https://web.archive.org/web/20260621200029/https://dev.java/learn/api/collections-framework/collection-interface/ )
In the sentence
"shoud" ought to be "should" .
In the sentence
"methods deal" seems right due to proximity, but it may be that "last batch ... deals" is appropriate since the "last batch of methods" is a singular subject, despite "of methods" (it is a single batch).
In the sentence
"then first of the unused cell of the array will be set to null" should be "the first unused cell of the array will be set to null" OR "the first of the unused cells of the array will be set to null" (either replace "first of the" with "first" OR replace "cell" with "cells").
In the sentence
"choosing ArrayList as you default implementation" should be "choosing ArrayList as your default implementation" ("you" should be "your" in this context).
In the latest version of https://dev.java/learn/api/collections-framework/sets/ (archived as is at https://web.archive.org/web/20260621212321/https://dev.java/learn/api/collections-framework/sets/ )
In the sentence
It is not clear where in this particular tutorial series TreeSet has already been demonstrated (I am familiar with it but I could not find any particular occurrence of TreeSet prior to this page in this tutorial series).
Could there be a link on "As you already saw" to avoid this confusion? (Or the team could just remove "As you already saw" and start with "Either you".)
Also, maybe "comparator" should be "Comparator" to be consistent with the casing and hyperlinking of other named classes and interfaces, though maybe the thinking here is this is some unspecified implementation of Comparator so can be lowercased.
In the sentence
the specification for tailSet(fromElement) says greater than or equal to , not greater than ; the description of headSet is accurate (intervals/ranges are usually closed-open, start point inclusive and end point exclusive).
In the sentence
the wrong overload is linked for each of these methods:
In the latest version of https://dev.java/learn/api/collections-framework/organization/ (archived as is at https://web.archive.org/web/20260621185555/https://dev.java/learn/api/collections-framework/organization/ )
In the heading (in the text, and on the sidebar)
"element" should be "elements" .
In the latest version of https://dev.java/learn/api/collections-framework/stacks-queues/ (archived as is at https://web.archive.org/web/20260621222720/https://dev.java/learn/api/collections-framework/stacks-queues/ ) ,
In the sentence
"and gives you" should be "and give you" .
In the sentence
"that do no implement" should be "that do not implement", in that "no" should be "not".
In the latest version of https://dev.java/learn/api/collections-framework/working-with-keys-and-values/ (archived as is https://web.archive.org/web/20260622004402/https://dev.java/learn/api/collections-framework/working-with-keys-and-values/ )
In the following sentences
"You can also get different sets" should probably be "You can also get different Collections" as "values(): returns an instance of Collection" not a Set, though the other two return Sets ( because Sets are Collections it is ok to refer to the first two cases as Collection, but not to refer to the third case as a Set).
In the latest version of https://dev.java/learn/api/collections-framework/sorted-maps/ (archived as is at https://web.archive.org/web/20260622174346/https://dev.java/learn/api/collections-framework/sorted-maps/ )
In the sentences
one can get the impression that TreeMap is the sole implementation provided by the Java Collections Framework, when there is also ConcurrentSkipListMap available which implements both interfaces. It may be worth noting this in passing; skip lists are not just for concurrent situations either. Since there are only two implementations provided in the Java Collections Framework, it may be worth updating this to mention both (it is not a long list), before continuing to focus on TreeMap which is the most commonly used. Or, one could only mention TreeMap but avoid giving the impression it is the one and only by saying something like "A class provided by the Java Collections Framework that implements both interfaces is TreeMap ."
In the latest version of https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ (archived as is at https://web.archive.org/web/20260622182311/https://dev.java/learn/api/collections-framework/arraylist-vs-linkedlist/ )
In the sentence
"bench" should be "benchmark".
In the sentences
It may be dangerous to tell readers that the policy for growing an ArrayList is to multiply by 1.5x, as per the documentation:
(from https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/ArrayList.html , bold added )
To achieve a constant amortized time cost, ArrayList could scale by any factor, not just 1.5, or perhaps implement a more complicated growth policy.
It does CURRENTLY try to scale by 1.5x in OpenJDK (the specification gives them the freedom to change this), but it has a more complicated policy as one approaches the limit on the maximum length of an array.
In the sentence
"the node" should be "the nodes".
In the sentence
"On the overall," should be "Overall,".
In the sentence
"as different JVM may handle memory differently" should be "as different JVMs may handle memory differently" ("JVM" should be updated to "JVMs" BUT in the first occurrence only).
In the sentence
"as that you can avoid if" should be "and you can avoid this if".
Thanks very much!
JosePaumard commentedon Jun 25, 2026
Thank you again for your report! A fix is on its way.
As for the ArrayDeque discussion. ArrayDeque is mentionned in the next sentence after the one you quote ("So if your application needs a Last In, First Out..."). Also keep in mind that AD cannot be a drop-in replacement of LL, since it does not accept null values, which is also mentionned on this page.
The page you quote (ArrayList vs. LinkedList) is a performance study (CPU and Memory wise) of both implementation, as List implementations. Reason why ArrayDeque is not on this picture.
The JDK JavaDoc mentions Stack, which is an old class from JDK 1 that should not be used anymore, and that ArrayDeque that may outperform LinkedList on Queue / Stack operations. A closer look shows that LinkedList is faster on peek, and slower on push and pop. But that would need a much more in depth comparison. Maybe some work for later.
willy-b commentedon Jun 29, 2026
Excellent!
Here are some more items in this tutorial series I have found during additional review that the dev.java team may be interested to fix.
In the latest version of https://dev.java/learn/api/collections-framework/collection-interface/ (archived as is at https://web.archive.org/web/20260628211938/https://dev.java/learn/api/collections-framework/collection-interface/ ),
In the sentence
it is promised that we will get a complementary example using HashSet , but no such example occurs within the page in the current version.
In the sentence
"removeAll()" links to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Collection.html#addAll(java.util.Collection) which is the opposite of the intended method.
It should link to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Collection.html#removeAll(java.util.Collection) .
In the latest version of https://dev.java/learn/api/collections-framework/lists/ (archived as is at https://web.archive.org/web/20260629000909/https://dev.java/learn/api/collections-framework/lists/ )
In the description of methods added in the ListIterator interface
ListIterator's add(element) is not described (though set(element) is), which seems like an unintentional omission (should be added).
In the sentence
"you can to use" should be "you can use"
In the code snippet under "Reversing a List", there is a typo:
Obviously "IO.prinln" was intended by the dev.java team to be "IO.println".
In the latest version of https://dev.java/learn/api/collections-framework/intro/ (archived as is at https://web.archive.org/web/20260628175138/https://dev.java/learn/api/collections-framework/intro/?no_cache=true )
In the sentence
"You will learn in this part are the most useful data structures" is not grammatical. There are multiple ways to fix it. One way to rephrase it might be "What you will learn in this part are the most useful data structures."
Or the word "are" could be removed for "You will learn, in this part, the most useful data structures" (also adding commas around "in this part").
In the sentence
"HashTable" should be "Hashtable" to match the official capitalization in the JDK (unlike HashMap, which capitalizes Map, Hashtable does NOT capitalize table).
In the sentence
"that you master well" seems like an unusual phrasing, so you might double check whether or not this was intended to be "that you have mastered well".
In the latest version of https://dev.java/learn/api/collections-framework/organization/ (archived as is at https://web.archive.org/web/20260628144813/https://dev.java/learn/api/collections-framework/organization/ )
In the sentence
"may be already familiar" seems much less frequently used than "may already be familiar", so you may wish to change this.
In the sentences
"You can get the lowest element" can mention first() (and since Java 21 also getFirst() ),
"and [you can get] the largest element" can mention last() (and since Java 21 also getLast() ),
"or greater than" should be "or greater than or equal to" per the specification for tailSet .
Finally, "lesser than" would probably be clearer as "less than" ("lesser than" is not typical, see Google ngrams below)
In the latest version of https://dev.java/learn/api/collections-framework/sets/ (archived as is at https://web.archive.org/web/20260629004135/https://dev.java/learn/api/collections-framework/sets/ )
It's a tiny thing but in the sentences
It seems unintentional that the last occurrence of "TreeSet" is not linked to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/TreeSet.html like the other two occurrences.
Similarly, the 2nd occurrence of "Comparator" is hyperlinked, but not the first (so the dev.java team may want to make both hyperlinked to be consistent).
In the sentences
"returns" should be "return" because the subjects are plural (2 methods each).
In the sentence
"greater element" should be "greatest element", and
"lesser than" would probably be clearer as "less than" ("lesser than" is not typical, see Google ngrams below)
In the sentence
"return and removes" should be "return and remove"
In the latest version of https://dev.java/learn/api/collections-framework/factory-methods/ (archived as is https://web.archive.org/web/20260629013833/https://dev.java/learn/api/collections-framework/factory-methods/ )
In the dev.java text
There appears to be potential confusion between the concepts of umodifiable and immutable as defined in the Collections Framework documentation (see https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/doc-files/coll-overview.html ).
Per the JDK documentation (from https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/doc-files/coll-overview.html , archived as is at https://web.archive.org/web/20260629140150/https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/doc-files/coll-overview.html )
> Collections that do not support modification operations (such as add, remove and clear) are referred to as unmodifiable. [...]
> Collections that additionally guarantee that no change in the Collection object will be visible are referred to as immutable. [...]
and (from https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Collection.html#unmodview , archived as is at https://web.archive.org/web/20260629140205/https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Collection.html#unmodview )
So the cited dev.java text (under the current heading "Wrapping a Collection in an Immutable Collection") should use "unmodifiable" instead of "immutable" (like the JDK does) in almost all places when referring to the output of the Collections methods labeled "unmodifiable" (consistent with the framework itself).
Thus e.g. in the following sentence in the dev.java article https://web.archive.org/web/20260629013833/https://dev.java/learn/api/collections-framework/factory-methods/
in "immutable collection", "collection" should be "wrapper" (or "wrapper collection" or "view collection", as the framework uses "view" instead of "wrapper" in these cases) and "immutable" should be "unmodifiable". The wrapper is an unmodifiable Collection, so you cannot mutate through it, but if it is a view onto a modifiable Collection which is modified directly elsewhere, then the unmodifiable view/wrapper Collection is NOT immutable, only unmodifiable, which is why it changes.
And the heading
should be updated to "Wrapping a Collection in an Unmodifiable Collection".
Some places are correct and do not need to change, e.g.:
is a correct use of "immutable".
But especially in the code example where the unmodifiableList viewing a mutable Collection is being updated,
"immutableStrings" should be "unmodifiableStrings" or "unmodifiableViewOfStrings".
Thanks very much for all the excellent content! It is appreciated, as is the opportunity to give back by reporting potential issues I find while reviewing it.
JosePaumard commentedon Jun 30, 2026
Thanks again for your report! A fix is on its way.
As for the immutable / unmodifable thing. I removed all reference to immutable, as this is a never-ending debate.
willy-b commentedon Jul 2, 2026
Thanks so much!
Unfortunately, I see what appear to be a few regressions in the dev.java team changes made in response to my comment above ( #206 (comment) ).
Here I reproduce the relevant parts of my comment with comments inline about what was not changed as expected
or where errors appear to have been introduced
(tl;dr dev.java team's new description of a nonexistent "addElement(element)" method on ListIterator instead of "add(element)" as requested for https://dev.java/learn/api/collections-framework/lists/ and e.g. the new sidebar-heading mismatch of "Unmodifiable" in the text and "Imutable" also with one "m" in the sidebar on https://dev.java/learn/api/collections-framework/factory-methods/ ; though the sidebar typo predates this ticket (see archived version at the old URL https://web.archive.org/web/20250805165813/https://dev.java/learn/api/collections-framework/immutable-collections ), also I did not recommend that heading to be changed).
[Parts not in "[", "]" are from my earlier comment
https://github.com/java/devjava-content/issues/206#issuecomment-4834074228]In the [previously reported] version of https://dev.java/learn/api/collections-framework/lists/ (archived as [it was] at https://web.archive.org/web/20260629000909/https://dev.java/learn/api/collections-framework/lists/ )
[update: there was unfortunately a mistake added by the dev.java team in https://web.archive.org/web/20260701135613/https://dev.java/learn/api/collections-framework/lists/ here:
the name of the method is "add" not "addElement" so it should be "add(element)" (as I had written in my comment) NOT "addElement(element)" .
Also the dev.java team may mention that "This call increases by one the value that would be returned by a call to nextIndex or previousIndex."]
[Parts not in "[", "]" are from my earlier comment
https://github.com/java/devjava-content/issues/206#issuecomment-4834074228]In the [previously reported] version of https://dev.java/learn/api/collections-framework/factory-methods/ (archived as [it was] https://web.archive.org/web/20260629013833/https://dev.java/learn/api/collections-framework/factory-methods/ )
In the dev.java text
There appears to be potential confusion between the concepts of unmodifiable and immutable as defined in the Collections Framework documentation (see https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/doc-files/coll-overview.html ).
Per the JDK documentation (from https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/doc-files/coll-overview.html , archived as is at https://web.archive.org/web/20260629140150/https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/doc-files/coll-overview.html )
and (from https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Collection.html#unmodview , archived as is at https://web.archive.org/web/20260629140205/https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/Collection.html#unmodview )
So the cited dev.java text (under the current heading "Wrapping a Collection in an Immutable Collection") should use "unmodifiable" instead of "immutable" (like the JDK does) in almost all places when referring to the output of the Collections methods labeled "unmodifiable" (consistent with the framework itself).
Thus e.g. in the following sentence in the dev.java article https://web.archive.org/web/20260629013833/https://dev.java/learn/api/collections-framework/factory-methods/
in "immutable collection", "collection" should be "wrapper" (or "wrapper collection" or "view collection", as the framework uses "view" instead of "wrapper" in these cases) and "immutable" should be "unmodifiable". The wrapper is an unmodifiable Collection, so you cannot mutate through it, but if it is a view onto a modifiable Collection which is modified directly elsewhere, then the unmodifiable view/wrapper Collection is NOT immutable, only unmodifiable, which is why it changes.
[confirmed fixed by dev.java team in a slightly different way in https://web.archive.org/web/20260701133510/https://dev.java/learn/api/collections-framework/factory-methods/ ]
And the heading
should be updated to "Wrapping a Collection in an Unmodifiable Collection".
[specific item here was fixed by the dev.java team in https://web.archive.org/web/20260701133510/https://dev.java/learn/api/collections-framework/factory-methods/ ,
BUT other headings were updated which can remain as Immutable (I only recommended that "Wrapping a Collection in an Immutable Collection" be updated, but the others have been updated by the dev.java as well),
and the first heading, which can (1) stay Immutable is also (2) in any case now mismatched between the text ("Unmodifiable") and the sidebar ("Imutable"[sic, typo by dev.java team]).
Note the typo in the sidebar is old, and was not introduced during this ticket: see the archived version at the old URL https://web.archive.org/web/20250805165813/https://dev.java/learn/api/collections-framework/immutable-collections .]
Some places are correct and do not need to change, e.g.:
is a correct use of "immutable".
[I disagree with the change that was made here, as this was replaced with "unmodifiable" in https://web.archive.org/web/20260701133510/https://dev.java/learn/api/collections-framework/factory-methods/ , I don't think it makes sense to say "unmodifiable" here as defensive copying is to ensure immutability ; the view is indeed unmodifiable per the Collections Framework definition of not allowing mutation operations on that object, but shows changes in the backing collection (not immutable). It would be immutable if the backing collection were copied before being wrapped with the reference to the mutable backing collection discarded or protected .]
But especially in the code example where the unmodifiableList viewing a mutable Collection is being updated,
"immutableStrings" should be "unmodifiableStrings" or "unmodifiableViewOfStrings". [confirmed fixed by dev.java team in a slightly different way in https://web.archive.org/web/20260701133510/https://dev.java/learn/api/collections-framework/factory-methods/ ]
Then these are not regressions but rather items either not fixed (apparently unintentionally, not intentional "won't fix" which would be fine) or for which I have remaining comments the dev.java team MAY want to address.
[Parts not in "[", "]" are from my earlier comment
https://github.com/java/devjava-content/issues/206#issuecomment-4834074228]In the [previously reported] version of https://dev.java/learn/api/collections-framework/collection-interface/ (archived as [it was] at https://web.archive.org/web/20260628211938/https://dev.java/learn/api/collections-framework/collection-interface/ ),
In the sentence
it is promised that we will get a complementary example using HashSet , but no such example occurs within the page in the current version.
[appears NOT fixed yet https://web.archive.org/web/20260701135507/https://dev.java/learn/api/collections-framework/collection-interface/ , maybe just replace "as you will see in the following" with "as you will see later in this tutorial series" or something ]
[Parts not in "[", "]" are from my earlier comment
https://github.com/java/devjava-content/issues/206#issuecomment-4834074228]In the [previously reported] version of https://dev.java/learn/api/collections-framework/sets/ (archived as [it was] at https://web.archive.org/web/20260629004135/https://dev.java/learn/api/collections-framework/sets/ )
"returns" should be "return" because the subjects are plural (2 methods each).
[fixed by the dev.java team in https://web.archive.org/web/20260701140300/https://dev.java/learn/api/collections-framework/sets/
BUT "return you" might be better as "return to you" , and the 2nd description of SortedSet here (unlike previous page which just got updated) doesn't yet mention getFirst/getLast added in Java 21 when mentioning first/last, so that may be good to add]
Thanks very much!
JosePaumard commentedon Jul 3, 2026
Thank you again for report! A fix is on its way.
As for the immutable / unmodifiable stuff. Since you have reflection, nothing is actually immutable in these parts of the API. Plus, with Valhalla round the corner (it is!) the meaning of immutability is changing. I don't know if the Collections Framework wording will be updated, but it will clearly sound dated at some point. So I changed all the wording to unmodifiable,
willy-b commentedon Jul 11, 2026
Thanks, most of what I reported above was addressed (I assume most of those ignored are intentional "won't fix" but ask about one of them at the bottom of this comment)!
Here are some mismatched links I have found in the latest versions of the pages in this tutorial series.
In the latest version of https://dev.java/learn/api/collections-framework/organization/ (archived as is https://web.archive.org/web/20260710223911/https://dev.java/learn/api/collections-framework/organization/?no_cache=true )
In the sentence
the URL for "last()" has a typo, https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/SortedSet.html#lasft()
with "lasft" (extra "F") instead of "last".
It should be https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/SortedSet.html#last() .
In the latest version of https://dev.java/learn/api/collections-framework/sorted-maps/ (archived as is at https://web.archive.org/web/20260710225705/https://dev.java/learn/api/collections-framework/sorted-maps/ )
In the sentences
"headMap(toKey, inclusive)" links to the wrong overload (not the 2-argument one described), https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/NavigableMap.html#headMap(K)
instead of to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/NavigableMap.html#headMap(K,boolean) .
"tailMap(fromKey, inclusive)" links to the wrong overload (not the 2-argument one described), https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/NavigableMap.html#tailMap(K)
instead of to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/NavigableMap.html#tailMap(K,boolean) .
Separately,
I previously reported the following which is still an issue as of 2026-07-10 US PT ( https://web.archive.org/web/20260711005831/https://dev.java/learn/api/collections-framework/collection-interface/?no_cache=true&nonce=1 ):
I still don't see any meaningful change for this particular sentence as of https://web.archive.org/web/20260711005831/https://dev.java/learn/api/collections-framework/collection-interface/?no_cache=true&nonce=1 , as it now reads:
You did add a sentence afterwards (but which is not obviously connected; "learn more about Set" in a separate section does not seem to refer to "in the following example" of the last sentence):
when an example on HashSet does not occur on this page (it still seems to suggest there is a specific code example coming up demonstrating HashSet). Thus I still recommend (you can acknowledge "won't fix" if you like of course) that it say "as you will see later in this tutorial series" or tie it directly into your next sentence mentioning more Set content will be covered on a later section of the tutorial (different page), or add a HashSet example.
Thanks so much!
JosePaumard commentedon Jul 11, 2026
Thank you again for your comments! A fix is on its way.
As for your last comment: I just added an example with a HashSet.
willy-b commentedon Jul 13, 2026
Thanks! I see the following items in the latest version of this tutorial.
In the latest version of https://dev.java/learn/api/collections-framework/sorted-maps/ (archived as is at https://web.archive.org/web/20260712070012/https://dev.java/learn/api/collections-framework/sorted-maps/ )
Reported earlier but still not fixed in the latest
In the sentence
"headMap(toKey, inclusive)" links to the wrong overload, linking to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/NavigableMap.html#headMap(K)
when the link SHOULD BE to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/NavigableMap.html#headMap(K,boolean) .
In the latest version of https://dev.java/learn/api/collections-framework/lists/ (archived as is at https://web.archive.org/web/20260713000721/https://dev.java/learn/api/collections-framework/lists/ )
In the sentence
"orginal" should be "original" .
In the latest version of https://dev.java/learn/api/collections-framework/maps/ (archived as is at https://web.archive.org/web/20260713002109/https://dev.java/learn/api/collections-framework/maps/ )
In the example code output for "Updating and Removing Existing Key / Value Pairs"
Where the line
Current ALice age: 26is not produced by the code shown in the page currently and should be removed from the expected output.In the latest version of https://dev.java/learn/api/collections-framework/maps-and-lambdas/ (archived as is at https://web.archive.org/web/20260713003221/https://dev.java/learn/api/collections-framework/maps-and-lambdas/?nonce=1 )
In the sentence
"exising" should be "existing".
In the sentence
"Whic" should be "Which"
Thanks so much!
JosePaumard commentedon Jul 13, 2026
Thank you again for your report! A fix is on its way.
willy-b commentedon Jul 14, 2026
Hey, for the page https://dev.java/learn/api/collections-framework/collection-interface/ ,
it looks like there's been a regression in one of the dev.java team's recent changes (note I do not get to review changes before they go out).
As of http://web.archive.org/web/20260714105633/https://dev.java/learn/api/collections-framework/collection-interface/?nonce=1
the code box has been changed from a plain code snippet to an interactive dev.java playground for the example including
compare to the OLDER version https://web.archive.org/web/20260628144825/https://dev.java/learn/api/collections-framework/collection-interface/ which did not have that code box configured as runnable,
and so did NOT need User defined (did not need to be a self-contained example),
but as of the latest (archived as is at http://web.archive.org/web/20260714105633/https://dev.java/learn/api/collections-framework/collection-interface/?nonce=1 )
this example now has a run button implying it is a complete executable example, which it is not (it is missing a User class definition). Attempting to run that example fails with an error:
To make the example complete, a User class definition could be added to the top:
After which the expected output would show:
Earlier the dev.java team had that example configured non-runnable (making it ok to not be standalone):
Thanks!
JosePaumard commentedon Jul 14, 2026
Thank you again for your report! A fix is on its way.
willy-b commentedon Jul 16, 2026
Thanks so much! All items previously reported appear resolved, so I am closing this.
Not a blocker but as a side note I will comment that there is an inconsistent use of periods at the end of sentences in the bullet points on https://dev.java/learn/api/collections-framework/maps/ (archived as is at https://web.archive.org/web/20260716081031/https://dev.java/learn/api/collections-framework/maps/ ), see e.g. the bullet points in the section "Storing Key/Value Pairs in a Map".
And also at
https://dev.java/learn/api/collections-framework/sets/ ( archived as is at https://web.archive.org/web/20260716082222/https://dev.java/learn/api/collections-framework/sets/?nonce=1 )
where e.g. the sentence below appears twice, and the first time has no ending period but in the second does:
Thanks!