• 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]