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:
method invokation doesn't change state (unlike next() in iterator, that's why hasNext() exists)
and you can clearly and exlicitly say that value returned isn't exceptional case (unlike 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.
Right now I'm having the same problem.
I'll to solve with this code:
public static <T> void hasJustOne(T... values) {
hasJustOne(Predicates.notNull(), values);
}
public static <T> void hasJustOne(Predicate<T> predicate, T... values) {
Collection<T> filtred = Collections2.filter(Arrays.asList(values),predicate);
Preconditions.checkArgument(filtred.size() == 1);
}
Related
down bellow you can see two example methods, which are structured in the same way, but have to work with completely different integers.
You can guess if the code gets longer, it is pretty anoying to have a second long method which is doing the same.
Do you have any idea, how i can combine those two methods without using "if" or "switch" statements at every spot?
Thanks for your help
public List<> firstTestMethod(){
if(blabla != null){
if(blabla.getChildren().size() > 1){
return blabla.getChildren().subList(2, blabla.getChildren().size());
}
}
return null;
}
And:
public List<> secondTestMethod(){
if(blabla != null){
if(blabla.getChildren().size() > 4){
return blabla.getChildren().subList(0, 2);
}
}
return null;
}
Attempting to isolate common ground from 2 or more places into its own Helper method is not a good idea if you're just looking at what the code does without any context.
The right approach is first to define what you're actually isolating. It's not so much about the how (the fact that these methods look vaguely similar suggests that the how is the same, yes), but the why. What do these methods attempt to accomplish?
Usually, the why is also mostly the same. Rarely, the why is completely different, and the fact that the methods look similar is a pure coincidence.
Here's a key takeaway: If the why is completely different but the methods look somewhat similar, you do not want to turn them into a single method. DRY is a rule of thumb, not a commandment!
Thus, your question isn't directly answerable, because the 2 snippets are so abstractly named (blabla isn't all that informative), it's not possible to determine with the little context the question provides what the why might be.
Thus, answer the why question first, and usually the strategy on making a single method that can cater to both snippets here becomes trivial.
Here is an example answer: If list is 'valid', return the first, or last, X elements inside it. Validity is defined as follows: The list is not null, and contains at least Z entries. Otherwise, return null.
That's still pretty vague, and dangerously close to a 'how', but it sounds like it might describe what you have here.
An even better answer would be: blabla represents a family; determine the subset of children who are eligible for inheriting the property.
The reason you want this is twofold:
It makes it much easier to describe a method. A method that seems to do a few completely unrelated things and is incapable of describing the rhyme or reason of any of it cannot be understood without reading the whole thing through, which takes a long time and is error-prone. A large part of why you want methods in the first place is to let the programmer (the human) abstract ideas away. Instead of remembering what these 45 lines do, all you need to remember is 'fetch the eligible kids'.
Code changes over time. Bugs are found and need fixing. External influences change around you (APIs change, libraries change, standards change). Feature requests are a thing. Without the why part it is likely that one of the callers of this method grows needs that this method cannot provide, and then the 'easiest' (but not best!) solution is to just add the functionality to this method. The method will eventually grow into a 20 page monstrosity doing completely unrelated things, and having 50 parameters. To guard against this growth, define what the purpose of this method is in a way that is unlikely to spiral into 'read this book to understand what all this method is supposed to do'.
Thus, your question is not really answerable, as the 2 snippets do not make it obvious what the common thread might be, here.
Why do these methods abuse null? You seem to think null means empty list. It does not. Empty list means empty list. Shouldn't this be returning e.g. List.of instead of null? Once you fix that up, this method appears to simply be: "Give me a sublist consisting of everything except the first two elements. If the list is smaller than that or null, return an empty list", which is starting to move away from the 'how' and slowly towards a 'what' and 'why'. There are only 2 parameters to this generalized concept: The list, and the # of items from the start that need to be omitted.
The second snippet, on the other hand, makes no sense. Why return the first 3 elements, but only if the list has 5 or more items in it? What's the link between 3 and 5? If the answer is: "Nothing, it's a parameter", then this conundrum has far more parameters than the first snippet, and we see that whilst the code looks perhaps similar, once you start describing the why/what instead of the how, these two jobs aren't similar at all, and trying to shoehorn these 2 unrelated jobs into a single method is just going to lead to bad code now, and worse code later on as changes occur.
Let's say instead that this last snippet is trying to return all elements except the X elements at the end, returning an empty list if there are fewer than X. This matches much better with the first snippet (which does the same thing, except replace 'at the end' with 'at the start'). Then you could write:
// document somewhere that `blabla.getChildren()` is guaranteed to be sorted by age.
/** Returns the {#code numEldest} children. */
public List<Child> getEldest(int numEldest) {
if (numEldest < 0) throw new IllegalArgumentException();
return getChildren(numEldest, true);
}
/** Returns all children except the {#code numEldest} ones. */
public List<Child> getAllButEldest(int numEldest) {
if (numEldest < 0) throw new IllegalArgumentException();
return getChildren(numEldest, false);
}
private List<Child> getChildren(int numEldest, boolean include) {
if (blabla == null) return List.of();
List<Child> children = blabla.getChildren();
if (numEldest >= children.size()) return include ? children : List.of();
int startIdx = include ? 0 : numEldest;
int endIdx = include ? numEldest : children.size();
return children.subList(startIdx, endIdx);
}
Note a few stylistic tricks here:
boolean parameters are bad, because why would you know 'true' matches up with 'I want the eldest' and 'false' matches up with 'I want the youngest'? Names are good. This snippet has 2 methods that make very clear what they do, by using names.
That 'when extracting common ground, define the why, not the how' is a hierarchical idea - apply it all the way down, and as you get further away from the thousand-mile view, the what and how become more and more technical. That's okay. The more down to the details you get, the more private things should be.
By having defined what this all actually means, note that the behaviour is subtly different: If you ask for the 5 eldest children and there are only 4 children, this returns those 4 children instead of null. That shows off some of the power of defining the 'why': Now it's a consistent idea. Returning all 4 when you ask for 'give me the 5 eldest', is no doubt 90%+ of all those who get near this code would assume happens.
Preconditions, such as what comprises sane inputs, should always be checked. Here, we check if the numEldest param is negative and just crash out, as that makes no sense. Checks should be as early as they can reasonably be made: That way the stack traces are more useful.
You can pass objects that encapsulate the desired behavior differences at various points in your method. Often you can use a predefined interface for behavior encapsulation (Runnable, Callable, Predicate, etc.) or you may need to define your own.
public List<> testMethod(Predicate<BlaBlaType> test,
Function<BlaBlaType, List<>> extractor)
{
if(blabla != null){
if(test.test(blabla)){
return extractor.apply(blabla);
}
}
return null;
}
You could then call it with a couple of lambdas:
testMethod(
blabla -> blabla.getChildren().size() > 1,
blabla -> blabla.getChildren().subList(2, blabla.getChildren().size())
);
testMethod(
blabla -> blabla.getChildren().size() > 4,
blabla -> blabla.getChildren().subList(0, 2)
);
Here is one approach. Pass a named boolean to indicate which version you want. This also allows the list of children to be retrieved independent of the return. For lack of more meaningful names I choose START and END to indicate which parts of the list to return.
static boolean START = true;
static boolean END = false;
public List<Children> TestMethod(boolean type) {
if (blabla != null) {
List<Children> list = blabla.getChildren();
int size = list.size();
return START ?
(size > 1 ? list.subList(0, 2) : null) :
(size > 4 ? list.subList(2, size) :
null);
}
return null;
}
So suppose my application does lots of repetitive work, for example let's say my application checks lots of various Lists if they're empty or not. There are two methods by which I can accomplish this functionality - (there maybe other methods but since my goal is to understand the difference of the two methods and not the functionality itself here we go)
Method 1 - Tradition Method
public boolean isEmptyOrNull(List list)
{
return list != null && !list.isEmpty();
}
Method 2 - Lambda Way
Assuming we have created a functional interface with class name Demo and boolean isEmptyOrNull as the function.
Demo var = list -> list != null && !list.isEmpty();
So each time I wish to check a list I can either use Method 1 or 2 by using isEmptyOrNull(myList) or var.isEmptyOrNull(myList) respectively.
My question is why should I use Method 1 and not Method 2 and vice versa. Is there some performance aspect or some other aspect as to why I should prefer one method over the other !?
Oof, where to start.
Your idea of what null is, is broken.
isEmptyOrNull is a code smell. You shouldn't have this method.
null is a stand-in value that necessarily can mean 'not initialised', because that's built into java itself: Any field that you don't explicitly set will be null. However, it is very common in APIs, even in java.* APIs, that null can also mean 'not found' (such as when you call map.get(someKeyNotInTheMap)), and sometimes also 'irrelevant in this context', such as asking a bootstrapped class for its ClassLoader.
It does not, as a rule, mean 'empty'. That's because there is a perfectly fine non-null value that does a perfect job representing empty. For strings, "" is the empty string, so use that, don't arbitrarily return null instead. For lists, an empty list (as easy to make as List.of()) is what you should be using for empty lists.
Assuming that null semantically means the exact same thing as List.of() is either unneccessary (the source of that list wouldn't be returning null in the first place, thus making that null check unneccessary) or worse, will hide errors: You erroneously interpret 'uninitialized' as 'empty', which is a fine way to have a bug and to have that result your app doing nothing, making it very hard to find the bug. It's much better if a bug loudly announces its presence and does so by pointing exactly at the place in your code where the bug exists, which is why you want an exception instead of a 'do nothing, silently, when that is incorrect' style bug.
Your lambda code does not compile
Unless Demo is a functional interface that has the method boolean isEmptyOrNull(List list);, that is.
The difference
The crucial difference is that a lambda represents a method that you can reference. You can pass the lambda itself around as a parameter.
For example, java.util.TreeSet is an implementation of set that stores all elements you put inside in sorted order by using a tree. It's like building a phonebook: To put "Ms. Bernstein" into the phonebook, you open the book to the middle, check the name there, and if it's 'above' 'Bernstein', look at the middle of the first half. Keep going until you find the place where Bernstein should be inserted; even in a phonebook of a million numbers, this only takes about 20 steps, which is why TreeSet is fast even if you put tons of stuff in there.
The one thing TreeSet needs to do its job is a comparison function: "Given the name 'Maidstone' and 'Bernstein', which one should be listed later in the phone book"? That's all. If you have that function then TreeSet can do its job regardless of the kind of object you store in it.
So let's say you want to make a phone book that first sorts on the length of names, and only then alphabetically.
This requires that you pass the function that decrees which of two names is 'after' the other. Lambdas make this easy:
Comparator<String> decider = (a, b) -> {
if (a.length() < b.length()) return -1;
if (a.length() > b.length()) return +1;
return a.compareTo(b);
};
SortedSet<String> phonebook = new TreeSet<>(decider);
Now try to write this without using lambdas. You won't be able to, as you can't use method names like this. This doesn't work:
public void decider(String a, String b) {
if (a.length() < b.length()) return -1;
if (a.length() > b.length()) return +1;
return a.compareTo(b);
}
public SortedSet<String> makeLengthBook() {
return new TreeSet<String>(decider);
}
There are many reasons that doesn't work, but from a language design point of view: Because in java you can have a method named decider, and also a local variable named decider. You can write this::decider which would work - that's just syntax sugar for (a, b) -> this.decider(a, b); and you should by all means use that where possible.
There is no advantage in your example. Lamdas are often used in Object Streams, e.g for mapping or filtering by defining "adhoc functions" (that's what lambdas are).
Example: You have a list of strings named allStrings that you want to filter
List<String> longStrings = allStrings.stream()
.filter(s -> s.length() > 5) // only keep strings longer than 5
.collect(Collectors.toList()); // collect stream in a new list
Lambdas were added to introduce functional programming in java. It could be used as a shorthand for implementing single method interfaces (Functional interfaces). In the above example you provided, there is no much advantage. But lambdas could be useful in the below scenario:
Before lambdas
public Interface Calc{
int doCalc(int a, int b);
}
public class MyClass{
public void main(String[] args){
Calc x = new Calc() {
#Override
public int doCalc(int a, int b) {
return a + b;
}
};
System.out.println(x.doCalc(2, 3));
}
}
But with lambdas this could be simplified to
public class MyClass{
public void main(String[] args){
BiFunction<Integer, Integer, Integer> doCalc= (a, b) -> a + b;
System.out.println(doCalc.apply(2, 3));
}
}
This is especially helpful for implementing event listeners (in Android), in which case there are a lot of interfaces provided as part of the API with methods like onClick etc. In such cases lambdas could be useful to reduce the code.
Also with Java 8, streams were introduced and lambdas could be passed to filter/map the stream elements. Stream allow more readable code than traditional for loop / if-else in most cases.
I was reading a not related thread , when I read a comment: Any time I find myself needing a multi-line lambda, I move the lines to a private method and pass the method reference instead of the lambda.
I was asking: which is the correct way to implement this behaviour? With a boolean method as posted in comment, or with predicate?
Example:
let's say I wanna check if a Table is usable, where usable means isClean, isEmpty, hasChair.
class Table{
public boolean hasChair(){...}
public boolean isClean(){...}
public boolean isEmpty(){...}
}
I can implement my filtering test for my list List<Table> tablesList = Arrays.asList(table1,table2,table3,table4); in 2 ways: the first with boolean:
public boolean isUsable(){
return hasChair() && isClean() && isEmpty();
}
And use it with tablesList.stream().filter(Table::isUsable)
The second way is with predicate:
public Predicate<Table> isUsable(){
return table -> table.isEmpty() && table.isClean() && table.hasChair();
}
Usable with tablesList.stream().filter(isUsable())
Which is the correct implementation? Why choose one instead of other? Is there any big difference?
I think you meant for the second example
public static Predicate<Table> isUsable(){
return table -> table.isEmpty() && table.isClean() && table.hasChair();
}
Which might already suggest this form is likely to confuse the reader. Without static you could write table.isUsable() or Table::isUsable but it wouldn't do what you think.
Which is the correct implementation?
I would prefer the Table::isUsable as it can also be used as table.isUsable for an instance.
Why choose one instead of other?
I feel the first example is more natural and less confusing.
The second form is more useful for manipulating Predicates e.g. Predicate.or(Predicate)
Is there any big difference?
In this case, using a Stream is likely to be slower, but more importantly, more likely to confuse.
One advantage of the method returning a Predicate is it could be added to any class e.g. you can't alter Table for some reason.
Having Predicate<Table> isUsable() assumes that you would always require that logic to be used in places that require a Predicate<Table> instance, which is a limitation.
On the other hand, having boolean isUsable() gives you the flexibility of using Table::isUsable where a Predicate<Table> is required, or using Table::isUsable as implementation of some other functional interfaces (that matches the signature of that method) or directly calling t.isUsable() for a specific Table instance. Hence I find this alternative more useful.
static List<Predicate<Table>> predicateList = Arrays.asList(Table::hasChair, Table::isClean);
static boolean isUsable(Table table) {
return predicateList.stream().allMatch(p -> p.test(table));
}
use isUsable:
List<Table> tablesList = ...
Stream<Table> usableTables = tablesList.stream().filter(Table::isUsable);
I've seen code as below:
if (!substanceList.isEmpty() && (substanceList.size() > 0))
{
substanceText = createAmountText(substanceList);
}
Would the following be a valid refactor?
if (!substanceList.isEmpty())
{
substanceText = createAmountText(substanceList);
}
I would be grateful for an explanation of the above code and whether the second version may cause errors?
If in doubt, read the Javadoc:
Collection.isEmpty():
Returns true if this collection contains no elements.
Collection.size():
Returns the number of elements in this collection
So, assuming the collection is implemented correctly:
collection.isEmpty() <=> collection.size() == 0
Or, conversely:
!collection.isEmpty() <=> collection.size() != 0
Since the number of elements should only be positive, this means that:
!collection.isEmpty() <=> collection.size() > 0
So yes, the two forms are equivalent.
Caveat: actually, they're only equivalent if your collection isn't being modified from another thread at the same time.
This:
!substanceList.isEmpty() && (substanceList.size() > 0)
is equivalent to, by the logic I present above:
!substanceList.isEmpty() && !substanceList.isEmpty()
You can only simplify this to
!substanceList.isEmpty()
if you can guarantee that its value doesn't change in between evaluations of substanceList.isEmpty().
Practically, it is unlikely that you need to care about the difference between these cases, at least at this point in the code. You might need to care about the list being changed in another thread, however, if it can become empty before (or while) executing createAmountText. But that's not something that was introduced by this refactoring.
TL;DR: using if (!substanceList.isEmpty()) { does practically the same thing, and is clearer to read.
The only difference between the first and the second approach is that the first approach performs a redundant check. nothing else.
Thus, you'd rather avoid the redundant check and go with the second approach.
Actually, you can read the source code downloaded in the JDK:
/**
* Returns <tt>true</tt> if this list contains no elements.
*
* #return <tt>true</tt> if this list contains no elements
*/
public boolean isEmpty() {
return size == 0;
}
I think that this settles all the queries.
Implementation of isEmpty() in AbstractCollection is as follows:
public boolean isEmpty() {
return size() == 0;
}
So you can safely assume that !list.isEmpty() is equivalent to list.size() > 0.
As for "what is better code", if you want to check if the list is empty or not, isEmpty() is definitely more expressive.
Subclasses might also override isEmpty() from AbstractCollection and implement in more efficient manner than size() == 0. So (purely theoretically) isEmpty() might be more efficient.
The javadocs for Collection.size() and Collection.isEmpty() say:
boolean isEmpty()
Returns true if this collection contains no elements.
int size()
Returns the number of elements in this collection
Since "contains no elements" implies that the number of elements in the collection is zero, it follows that list.isEmpty() and list.size() == 0 will evaluate to the same value.
I want to some explanation of above code
The second version is correct. The first version looks like it was written either by an automatic code generator, or a programmer who doesn't really understand Java. There is no good reason to write the code that way.
(Note: if some other thread could be concurrently modifying the list, then both versions are problematic unless there is proper synchronization. If the list operations are not synchronized then may be memory hazards. But in the first version, there is also the possibility of a race condition ... where the list appears be empty and have a non-zero size!)
and want to know second way may be caused some error.
It won't.
Incidentally list.isEmpty() is preferable to list.size() == 0 for a couple of reasons:
It is more concise (fewer characters).
It expresses the intent of your code more precisely.
It may be more efficient. Some collection implementations may need to count the elements in the collection to compute the size. That may be an O(N) operation, and could other undesirable effects. For example, if a collection is a lazy list that only gets reified as you iterate the elements, then calling size() may result in excessive memory use.
Yes, it can be refactored as you did. The issue with both approaches is that you would do the check every time you want to call the method createAmountText on a List. This means you would be repeating the logic, a better way would be to use DRY (don't Repeat Yourself) principle and factor these checks into your method.
So your method's body should encapsulated by this check.
It should look like:
<access modifier> String createAmountText(List substanceList){
if(substanceList != null && !substanceList.isEmpty()){
<The methods logic>
}
return null;
}
Sure - the two methods can be used to express the same thing.
But worth adding here: going for size() > 0 is somehow a more direct violation of the Tell, don't ask principle: you access an "implementation detail", to then make a decision based on that.
In that sense, isEmpty() should be your preferred choice here!
Of course, you are still violating TDA when using isEmpty() - because you are again fetching status from some object to then make a decision on it.
So the really best choice would be to write code that doesn't need at all to make such a query to internal state of your collection to then drive decisions on it. Instead, simply make sure that createAmountText() properly deals with you passing in an empty list! Why should users of this list, or of that method need to care whether the list is empty or not?!
Long story short: maybe that is "over thinking" here - but again: not using these methods would lead you to write less code! And that is always an indication of a good idea.
Is there a method like this one in the JDK or Google Guava
public static <T> Collection<T> safe(Collection<T> collection) {
if (collection == null) {
return new ArrayList<>(0);
} else {
return collection;
}
}
which makes it easy to not crash on a an enhanced loop if something returns a null list for example
for (String string : CollectionUtils.safe(foo.canReturnANullListOfStrings())) {
// do something
}
would not crash.
I looked around but could not find any such method, and I am wondering if I missed it or if there is a reason why such a handy method is not handy and therefore not included?
Objects.firstNonNull(list, ImmutableList.<Foo>of());
There's no need for a specialized method, and this is indeed the solution we recommend you use immediately whenever you get a potentially-null collection from a naughty API that ideally shouldn't do that in the first place.
Apache Collections 4 has a generic method ListUtils.emptyIfNull(List<T> list)
Here is the doc: https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/ListUtils.html
In Java 8 it is possible to use this:
Optional.ofNullable(foo.canReturnANullListOfStrings()).orElse(Collections.emptyList());
Update for Java 9:
java.util.Objects.requireNonNullElse(collection, List.<T>of())
The <T> is still required.
So there does not exist a function to my knowledge of this sort. However writing one is trivial as you have shown above. The reasoning behind why it might not have been included is because null has a specific meaning and it might not be appropriate to return an empty Collection when one gets passed around. Generally (in my experience) when a null value enters the system something failed higher up the chain or an invalid value was not properly sanitized.