Skip to content
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

Provide an Iterables.tail() method #1906

Open
dimo414 opened this issue Dec 8, 2014 · 7 comments
Open

Provide an Iterables.tail() method #1906

dimo414 opened this issue Dec 8, 2014 · 7 comments

Comments

@dimo414
Copy link
Contributor

dimo414 commented Dec 8, 2014

I have a need to select the most recent n elements from a list that I know is ordered; for instance, to display data from the last ten years, in a (potentially long) list of data ordered by year.

For existing Lists it's tedious but not complicated to write out:

list.subList(Math.max(list.size() - n, 0), list.size())

though I'd argue the cleanliness of a simple .tail() method is still a nice win over the above. More valuable however is providing support for arbitrary Iterables, in order to avoid creating a copy of the whole data stream simply to take a small sublist. I imagine many users (myself included) simply absorb the cost of the full copy rather than take the time to implement a circular buffer or similar memory-efficient solution.

@lowasser
Copy link
Contributor

lowasser commented Dec 8, 2014

AFAIK, most languages' concept associated with the word "tail" would not be
the last n elements, but rather, equivalent to skipping the first n
elements. We might need a different name here.

On Mon Dec 08 2014 at 5:38:56 PM Michael Diamond notifications@github.com
wrote:

I have a need to select the most recent n elements from a list that I
know is ordered; for instance, to display data from the last ten years, in
a (potentially long) list of data ordered by year.

For existing Lists it's tedious but not complicated to write out:

list.subList(Math.max(list.size() - n, 0), list.size())

though I'd argue the cleanliness of a simple .tail() method is still a
nice win over the above. More valuable however is providing support for
arbitrary Iterables, in order to avoid creating a copy of the whole data
stream simply to take a small sublist. I imagine many users (myself
included) simply absorb the cost of the full copy rather than take the time
to implement a circular buffer or similar memory-efficient solution.


Reply to this email directly or view it on GitHub
#1906.

@cgdecker
Copy link
Member

cgdecker commented Dec 8, 2014

@lowasser: Hmm, any examples? We use skip for that, as does Java 8's Stream. tail is also a Unix command that outputs the last n lines of something.

@lowasser
Copy link
Contributor

lowasser commented Dec 8, 2014

Hmmm. I was thinking about Haskell, where "tail" refers to a list without
its first element, and doesn't really have a name for that feature that I
can think of?

I do think that e.g. FluentIterable.last(5) would be fairly unambiguous,
though, FWIW.

On Mon Dec 08 2014 at 5:52:40 PM Colin Decker notifications@github.com
wrote:

@lowasser https://github.com/lowasser: Hmm, any examples? We use skip
for that, as does Java 8's Stream. tail is also a Unix command that
outputs the last n lines of something.


Reply to this email directly or view it on GitHub
#1906 (comment).

@cgdecker
Copy link
Member

cgdecker commented Dec 8, 2014

Few thoughts:

  • It would be weird to get view behavior (via subList()) if the argument is a List and copy behavior if it isn't.
  • I would be ok with having a method on Iterables/FluentIterable that always does the copy behavior and a separate method on Lists that always does the view behavior.
  • This sounds fairly useful to me, but as with anything we'll need to get an idea about how generally useful it really is.

@vorburger
Copy link
Member

I understand that this issue is about a new method for getting the tailing/last/trailing N elements, but if anyone hits this page while searching for a method to find THE last element, as I just have, then FYI com.google.common.collect.Iterables's T getLast(Iterable iterable) is what you are looking for (it's optimized for List).

@kevinb9n
Copy link
Contributor

Note that our current offering here is EvictingQueue.

Queue<Foo> q = EvictingQueue.create(n);
q.addAll(everything);
for (Foo foo : q) { ... }

@dimo414
Copy link
Contributor Author

dimo414 commented Nov 1, 2016

Just to mention that a302923 makes EvictingQueue a little more efficient for this use-case, but it's still not as discoverable or intuitive as a method on Iterables would be.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants