-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Avoid list copy on reverse iteration #12297
Conversation
@sbordet @lorban an alternative approach would be to have the following method: /**
* <p>Returns an {@link Iterator} that efficiently iterates the passed list in reverse.</p>
* <p>The method is safe for concurrent modifications iff the list iterator itself is safe.</p>
* @param list the list
* @param <T> the element type
* @return An {@link Iterator} over the list elements in reverse order
* at the snapshot of the list represented by this call.
*/
public static <T> Iterator<T> reversed(List<T> list)
{
ListIterator<T> i;
try
{
int size = list.size();
switch (size)
{
case 0:
return Collections.emptyIterator();
case 1:
return list.iterator();
default:
i = list.listIterator(size);
}
}
catch (IndexOutOfBoundsException e)
{
// list was concurrently modified, so do this the hard way
i = list.listIterator();
while (i.hasNext())
i.next();
}
ListIterator<T> iterator = i;
return new Iterator<T>()
{
@Override
public boolean hasNext()
{
return iterator.hasPrevious();
}
@Override
public T next()
{
return iterator.previous();
}
};
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just javadocs niggles.
jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java
Outdated
Show resolved
Hide resolved
jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of modifying the iterations, we could keep TypeUtil.reverse()
and implement it this way:
public static <T> Iterable<T> reverse(List<T> list)
{
return () -> new Iterator<>()
{
private final ListIterator<T> listIterator = listIteratorAtEnd(list);
@Override
public boolean hasNext()
{
return listIterator.hasPrevious();
}
@Override
public T next()
{
return listIterator.previous();
}
@Override
public void remove()
{
listIterator.remove();
}
};
}
@lorban but that's another allocation. |
@sbordet possibly, but I sometimes feel we're a bit too obsessed with allocations so I'm tempted to spend some time looking at the JIT's efficiency at generating stack allocating code to deny/confirm if our fears are justified. In all case, I think exposing an iterator that delegates to |
Please fix the title of this PR, so it makes sense on a changelog. |
The resulting list would have an list with an iterator that does not match the However, I'm not totally opposed to my alternative, even though that is an extra allocation.... The resulting code is a little neater.... but then it pretty simple code anyway, and seldom touched, and clear what it does, so in this case the extra allocation doesn't get us much. |
updates from review Co-authored-by: Simone Bordet <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this could be improved, but I agree that this code is simple enough that no improvement would bring very much value; so LGTM the way it is.
The changes in #12289 introduced several list copy and reverses operations on every request.
This PR replaces that reversed list with a
ListIterator
used withprevious