Recently I had a need to do 'special case' scenario if only one element exist in collection. Checking for ...size() == 1
and retrieving by using ...iterator.next()
looked ugly so I've created two methods in home brew Collections class:
public class Collections {
public static <T> boolean isSingleValue(Collection<T> values) {
return values.size() == 1;
}
public static <T> T singleValue(Collection<T> values) {
Assert.isTrue(isSingleValue(values));
return values.iterator().next();
}
}
Few days ago I discovered that Guava has method called Iterables.getOnlyElement. It covers my need and replaces singleValue
, but I can't find match for isSingleValue
. Is that by design? Is it worth to put feature request for having Iterables.isOnlyElement
method?
EDIT: Since there were few upvotes I decided to open enhancement on guava - issue 957. Final resolution - 'WontFix'. Arguments are very similar to what Thomas/Xaerxess provided.
Well, you'd not gain much by replacing values.size() == 1
with a method, except you could check for null. However, there are methods in Apache Commons Collections (as well as in Guava, I assume) to do that.
I'd rather write if( values.size() == 1 )
or if( SomeHelper.size(values) == 1 )
than if( SomeHelper.isSingleValue(values) )
- the intent is much clearer in the first two approaches and it's as much code to write as with the third approach.
Just in addition to other answers (I was going to write something like @daveb who deleted his one: If there is not exactly one element, then Iterables#getOnlyElement
will throw an IllegalArgumentException
or NoSuchElementException
) - an answer to question why there isn't any Iterables.isSingleValue(Iterable)
in Guava.
I think you're making this wrong. If:
next()
in iterator, that's why hasNext()
exists)null
returned from Map#get(Object)
- it can be null value or it can mean that key wasn't found in map)there is no need for method checking if condition is true and then doing some operation (with assertion in it!) like in your sample code.
If you are absolutely sure that the iterable at this place cannot have size other than 1, than condition checking is redundant (exception is thrown in other cases).
If you want only get first element in non-empty collection - collection.iterator.next()
is perfectly OK (NoSuchElementException
is thrown if collection is empty).
If you don't know anything about collection's size than Iterables.getFirst(iterable, default)
is for you.
P.S. If your Collections#isSingleValue
used only locally here (hence could be private) that really means you don't need that check before calling Iterables#getOnlyValue
.
P.P.S. Another answer to your question about Guava's design could be Item 57 of Joshua Bloch's Effective Java - there are few different helper methods in Guava I mentioned before that explicitly say what is an exceptional case for each one; boolean check wasn't added becasuse of keeping API as small as possible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With