getFirst and getLast on Iterable
Brian Goetz
brian.goetz at oracle.com
Thu Apr 17 16:47:41 UTC 2014
In the course of JSR-335, we considered a number of possible methods on
Iterable. There are literally hundreds of methods that might "sensibly"
appear on Iterable; see RichIterable from GS-Collections or IEnumerable
from .NET for some examples. After considering the landscape, we
decided, basically, to not do any of them.
The reason is that Iterable is *so general* and *so ubiquitous* that
adding new methods at this stage would carry an unreasonable risk of
collision. When viewed through the lens of "what is an Iterable", the
meaning of a "getFirst()" is obvious enough. (getLast(), not so much;
this assumes there is a last, which is a bad assumption, given that
there's no size() or isKnownFinite() method.)
The problem is, in the context of some Foo that implements
Iterable<Bar>, methods like getFirst() or sorted() or filter() or ...
might not obviously mean in the context of Foo what they obviously mean
in the context of Iterable. Iterable is too general. And there are
zillions of outstanding Iterable classes now, so the risk is high.
So given the choice between adding a zillion new methods, and adding
zero (which is basically the choice, drawing the line is very hard and
will always be under pressure to move "just one more method to the
left"), we chose zero.
On 4/17/2014 7:52 AM, Otávio Gonçalves de Santana wrote:
> I would to add for news methods on Iterable, I believe it will helpful for
> many Java Developers.
>
>
> diff -r 3dd165facde7 test/java/util/Iterator/IteratorDefaults.java
>
> --- a/test/java/util/Iterator/IteratorDefaults.java Wed Apr 09 12:26:00
> 2014 -0700
>
> +++ b/test/java/util/Iterator/IteratorDefaults.java Wed Apr 16 23:25:56
> 2014 -0300
>
> @@ -399,6 +399,48 @@
>
> }
>
> }
>
>
>
> + public void testgetFirst() {
>
> +
>
> + List<Integer> source = Arrays.asList(1, 2, 3, 4);
>
> + int first = source.getFirst();
>
> + assertEquals(first, 1);
>
> +
>
> + List<String> emptySource = Collections.<String>emptyList();
>
> + assertNull(emptySource.getFirst());
>
> + }
>
> +
>
> + public void testgetFirstWithDefaultElement() {
>
> +
>
> + List<Integer> source = Arrays.asList(1, 2, 3, 4);
>
> + Integer defaultElement = 5;
>
> + assertEquals(source.getFirst(defaultElement), Integer.valueOf(1));
>
> +
>
> + List<Integer> emptySource = Collections.<Integer>emptyList();
>
> + assertEquals(emptySource.getFirst(defaultElement), defaultElement);
>
> +
>
> + }
>
> +
>
> + public void testgetLast() {
>
> +
>
> + List<Integer> source = Arrays.asList(1, 2, 3, 4);
>
> + int last = source.getLast();
>
> + assertEquals(last, 4);
>
> +
>
> + List<String> emptySource = Collections.<String>emptyList();
>
> + assertNull(emptySource.getLast());
>
> + }
>
> +
>
> + public void testgetLastWithDefaultElement() {
>
> +
>
> + List<Integer> source = Arrays.asList(1, 2, 3, 4);
>
> + Integer defaultElement = 5;
>
> + assertEquals(source.getLast(defaultElement), Integer.valueOf(4));
>
> +
>
> + List<Integer> emptySource = Collections.<Integer>emptyList();
>
> + assertEquals(emptySource.getLast(defaultElement), defaultElement);
>
> +
>
> + }
>
> +
>
> static class IteratorWithRemove implements Iterator {
>
>
>
> public boolean removed;
>
>
>
>
> diff -r 3dd165facde7 src/share/classes/java/lang/Iterable.java
>
> --- a/src/share/classes/java/lang/Iterable.java Wed Apr 09 12:26:00 2014
> -0700
>
> +++ b/src/share/classes/java/lang/Iterable.java Wed Apr 16 23:16:21 2014
> -0300
>
> @@ -100,4 +100,55 @@
>
> default Spliterator<T> spliterator() {
>
> return Spliterators.spliteratorUnknownSize(iterator(), 0);
>
> }
>
> +
>
> +
>
> + /**
>
> + * returns the first element, if empty will return {@code null}
>
> + * @return the first element or {@code null}
>
> + * @since 1.8
>
> + */
>
> + default T getFirst() {
>
> + return getFirst(null);
>
> + }
>
> +
>
> + /**
>
> + * returns the first element, if empty will return the default
>
> + * @param defaultValue - the default value to return if the iterable
> is empty
>
> + * @return the first element or default element
>
> + * @since 1.8
>
> + */
>
> + default T getFirst(T defaultValue) {
>
> + for (T element : this) {
>
> + return element;
>
> + }
>
> + return defaultValue;
>
> + }
>
> +
>
> + /**
>
> + * returns the last element, if empty will return {@code null}
>
> + * @return the first element or {@code null}
>
> + * @since 1.8
>
> + */
>
> + default T getLast() {
>
> +
>
> + return getLast(null);
>
> + }
>
> +
>
> + /**
>
> + * returns the last element, if empty will return the default
>
> + * @param defaultValue - the default value to return if the iterable
> is empty
>
> + * @return the last element or default element
>
> + * @since 1.8
>
> + */
>
> + default T getLast(T defaultValue) {
>
> +
>
> + T last = null;
>
> + for (T element : this) {
>
> + last = element;
>
> + }
>
> + if (Objects.isNull(last)) {
>
> + return defaultValue;
>
> + }
>
> + return last;
>
> + }
>
> }
>
More information about the core-libs-dev
mailing list