- make object implementing java.lang.Iterable accessible with SpEL indexing
- only read access is possible, as we cannot write an iterable object
- make compiler compatible
Comment From: sbrannen
Is it reasonable to support access to Iterable
objects via an index?
For example, the Javadoc for Collection
explicitly states:
Returns an iterator over the elements in this collection. There are no guarantees concerning the order in which the elements are returned (unless this collection is an instance of some class that provides a guarantee).
Thus, for many Collection
implementations and other Iterable
implementations, the order returned by the iterator()
method may potentially change between invocations, which would lead to unreliable evaluations for SpEL expressions making use of this proposed feature.
@aclement & @jhoeller, what your thoughts on the proposal?
Comment From: pilak
@sbrannen thank you for the interesting notice
In the Javadoc of java.util.List#iterator, we can read this:
Returns an iterator over the elements in this list in proper sequence.
So I guess that in most cases the Iterator will preserve the ordering, it would be worth to allow the access with Indexer.
Furthermore, if the user traverses the object in an indexing manner (using [n]), isn't that its own responsibility to know if the underlying Iterator is ordered or not?
Thanks for your advises
Comment From: sbrannen
Superseded by #26409
Comment From: sbrannen
I realize this issue was closed 3 years ago, but I discovered there are already ways to "index" into an Iterable
in SpEL.
In 4.2, @jhoeller added collection selection/projection support for Iterable
(see #17822).
In light of that I introduced dedicated tests to show this in action. Note that the Counter
implements Iterable
but is not a Collection
.
https://github.com/spring-projects/spring-framework/blob/43bbe8f3e8aa99436ac5c33fcff5a8795e00a2ed/spring-expression/src/test/java/org/springframework/expression/spel/SelectionAndProjectionTests.java#L169-L194
In summary, given an Iterable
available as #iterable
, if we supply true
as the selection expression (which basically means select all elements from the Iterable
in its iteration order and store them in a new List
), we can:
- select first element:
#iterable.^[true]
- select last element:
#iterable.$[true]
- select 2nd element:
#iterable.?[true][1]
- select 3rd element:
#iterable.?[true][2]