I'm trying my hand at using Optional as much as I can over normal null checks; and I ran into a suggestion by my IDE (IntelliJ):
Can be replaced by a singular expression in functional style.
Here is the code in question, the line in question:
Entry entry = maybeBytes.isPresent() ? Entry.deserialize(maybeBytes.get()) : new Entry();
I've looked a bit here, but couldn't find a usage or at least see one that would fit my case here. I'm pretty new to the lambda features.
How about:
Entry entry = maybeBytes.map(Entry::deserialize).orElseGet(Entry::new);
If maybeBytes contains a value, it will be passed to the function you provide to map(), and you'll get an Optional<Entry> with the result (and if maybeBytes was empty, you'll get an empty Optional<Entry>). orElseGet() will give you the contents of the Optional<Entry> if it's nonempty, and otherwise, it will give you the result of evaluating the function you pass to it (in this case, the constructor of Entry).
Pressing Alt+Enter when you see such suggestions will apply them, and you'll see the result yourself :)
In my case it was orElse() which fit to my needs. I do not needed to do extra deserialization.
instead of isPresent() combined with get() certainly does the trick…
return maybeBytes.isPresent() ? maybeBytes.get() : new Entry();
you can use
return maybeBytes.orElse(new Entry());
Related
So I've created a stream which comes from a List but I'm having some trouble converting it into a <ObjectType>, here's what I've tried:
ObjectType sco = getList().stream()
.filter(p -> p.getValue() == value)
.findFirst(); //also tried .orElse(null);
would anyone, please, be so kind as to suggest where I'm going wrong?
(I apologize if this has been asked before but I couldn't find a discussion on this particular topic (or didn't know the proper terms to search for))
Thanks in advance!
findFirst() gives you an Optional and you then have to decide what to do if it's not present. So findFirst().orElse(null) should give you the object or null if it's not present
You could just do a .get() on the Optional, but that could be regarded as poor practice since get() will throw an exception if Optional has no content. You should normally assert presence/absence of the Optional and decide what to do in each case (that's why it's there - so that you know something is truly optional and you have to determine what to do)
If you have an action you want to perform on object presence, and you don't want to do anything on absence, you can call .ifPresent() and provide a lambda as an argument. That will be called with the contained object, if present.
As of Java 9, a further solution would be to use Optional.ifPresentOrElse()
I think you may be looking for findFirst().or Else(null). findFirst() will return an Optional - empty in the case of an empty steam.
Unless I misunderstood your comment. Have you tried this, or did you try orElse(null) without findFirst()?
I know that once we create the stream off of a collection we should not modify collection while consuming the stream, However not sure if following approach works where I am modifying the entry inside the map and not adding or removing anything from it. Also, is this the right way to stream the map always and consume it ?
creepyCategoryStatuses.entrySet().stream().forEach(entry -> {
String creepyBlockResponse = (String) getBlockResponse(entry.getKey());
if (creepyBlockResponse.equalsIgnoreCase("block")){
entry.setValue(true);
//OR creepyCategoryStatuses(entry.getKey(), true);
}
});
This kind of modification is no problem as setting the value of an entry is not a structural modification. However, it’s worth noting that there are more Java 8 features than the Stream API or the forEach method:
creepyCategoryStatuses.replaceAll((key,value)->
((String)getBlockResponse(key)).equalsIgnoreCase("block")||value
);
does the job much easier. Note that ||value will retain the old value if the condition evaluates to false as in your original code.
Yes, such usage of Map seems to be legit. Note that in this case you don't need the stream. You can simply use
creepyCategoryStatuses.entrySet().forEach(entry -> {...});
According to your use-case, you could use replaceAll here:
creepyCategoryStatuses.replaceAll((k, v) -> ((String) getBlockResponse(k)).equalsIgnoreCase("block") ? true : v);
I always favor functional paradigms, so I would collect the new data into a new map, but that's a matter of taste.
I want to use Optional for a method which returns a List
Lets say the function is
public Output getListOfSomething() {
// In some cases there is nothing to return and hence it makes sense to have return
// type as Optional here
}
Hence the function looks like :
public Optional<List<String>> getListOfSomething() {
// return something only when there is some valid list
}
Now I want to do something if the list is present so something like :
Optional<List<String>> listOfSomething = getListOfSomething();
int size = 0;
listOfSomething.ifPresent(size = listOfSomething.get().size());
I am new to Optional and have gone through the articles about Optional and it seems like this should work however am getting syntax error in my IDE :
method ifPresent is not applicable for the arguments (void).
I wanted to get some help from developers who might be more fluent with lamdas in java 8.
It's important to think about the Semantics here.
Your method could return a List, or "no list".
If it returns a List, it could return an Empty list.
You should ask, "is there a semantic reason to distinguish between an Empty List, and No List?" Sometimes there is a good design reason to make the difference, but it is rare. Think long and hard before deciding that Empty and Null are different in your case. Part of the reason to avoid No List, is that it reduces "special cases" that the client code has to consider. For example, if they have to do something for every item returned, but you could also return null, they have to do a special check for null before going into a for each loop. A for each does nothing if the list is empty.
If a "No List" is distinct from an "Empty List" in your problem domain, then it is sometimes useful to return wrapper class that helps client code distinguish between those conditions, and handle them appropriately. Optional is one such generic class, but your domain may call for something more specific (even if it mimics the functionality of Optional, it might have better semantic definition).
The true functional-programming way is the following:
size = listOfSomething.map(List::size).orElse(0);
But it would be much better to return an empty List instead of Optional.
ifPresent requires a Consumer interface to work. You could do the following:
Optional<List<String>> listOfSomething = getListOfSomething();
Integer[] size = {0};
listOfSomething.ifPresent(list -> size[0]=list.size())
But as stated by Tagir Valeev it would be better to do:
size = listOfSomething.map(List::size).orElse(0);
And it would also be better to return an empty List or even a Stream maybe.
There's no doubt that in-out parameters leads to confused code since they may increase unexpected/unpredictabled side-effects.
So, many good programmers say :
Avoid in-out parameters for changing mutable method parameters. Prefer to keep parameters unchanged.
For a perfectionist programmer who expects his code to be the most clean and understandable, does this "rule" must be applied in all case ?
For instance, suppose a basic method for adding elements to a simple list, there's two ways :
First way (with in-out parameter):
private void addElementsToExistingList(List<String> myList){
myList.add("Foo");
myList.add("Bar");
}
and the caller being :
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
addElementsToExistingList(myList);
Second way without out parameter :
private List<String> addElementsToExistingList(List<String> originalList){
List<String> filledList = new ArrayList<String>(originalList); //add existing elements
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
and the caller being :
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(addElementsToExistingList(myList));
Pros of second way :
Parameter are not modified => no risk of unexpected side-effects for a new code reader.
Cons of second way :
Very verbose and very less readable ...
Of course, you would tell me that for a code as simple as this one, first way is really more convenient.
But, if we don't consider the difficulty of any concept/code, I juge the second way more logical and obvious for any readers (beginners or not).
However, it violates the CQS principle that consider "command" methods having void return with potential (but allowed since it's the convention) side-effects and "query" methods having a return type and without side-effects.
So, what should a motivate programmer adopt ? Mix of two accorging to the code case ? Or keep the "law" expecting to always avoid in-out parameters...
(Of course, method for adding Element is named for expliciting the example, and would be a bad name choice in real code).
I think the law should be:
Use what is more straight-forward, but always, always document the behavior of your methods extensively.
Your second example is a very nice case where without documentation you would have a guaranteed bug: the name of the method is addElementsToExistingList, but the method does not add elements to the existing list - it creates a new one. A counter-intuitive and misleading name, to say the least...
There is a third way. Wrap List<String> into a class that knows how to add elements to itself:
class ElementList {
private List<String> = new ArrayList<String>();
public void addElements(Element... elements);
}
I like this approach because it keeps the List implementation private. You don't have to worry if someone passes an immutable list to your method or whether parameters are modified. The code is simpler. Long method names like addElementsToExistingList are code smells that an object is trying to do something another object should be doing.
You should always document when mutating an object that is a parameter because otherwise this can have unintended side effects for the caller. In the first case I agree with the others that have commented that the method name is sufficient documentation.
In your second example, the elements that are already present in myList seem to be added twice. In fact you could entirely remove the parameter of the addElementsToExistingList method and rewrite it as:
private List<String> getElements() {
List<String> filledList = new ArrayList<String>();
filledList.add("Foo");
filledList.add("Bar");
return filledList;
}
List<String> myList = new ArrayList<String>();
//.......Several Instructions (or not) .....
myList.addAll(getElements());
Note that this code is not equivalent to your second example because the elements are only added once, but I think this is actually what you intended. This is the style that I usually prefer. This code is easier to understand and more flexible than the first example without adding extra code (it may degrade performance very slightly but this usually isn't a concern). The client of getElements() can now also do other things with the element list besides adding it to an existing collection.
It's fine to change/mutate parameters as long as it's documented. And of course with a method name of "addElementsToExistingList", what else should someone expect? However, as someone previously pointed out, your second implementation returns a copy and doesn't modify the original, so the method name is now misleading. Your first way is a perfectly acceptable way of doing things. The only other additional improvements is to possibly add a true/false value to the return indicating true if only all the elements were added to the list.
In the case of your example the name makes it clear - "addElementsToExistingList" to me seems pretty clearly to hint that you're going to .. er.. you know. But your concern would be justified with a less obvious name.
For example, in ruby this is commonly handled with naming conventions
"a".upcase => gives you the uppercase of the variable, leaves the original unchanged
"a".upcase! => alters the original variable
I am looking for a method to assure all objects contained in a Collect (List) return a specified value from a predicate.
Pseudo Code:
Collections.assertTrue(List<Ballons>, isBluePredicate)
I do not see this being possible with the current API (maybe I am not looking in the proper place)
If this does exist would the function exit when it first encounters a false value?
The Iterables.all(Iterable, Predicate) method is the normal way to do this; the assertion would need to be your own.
Guava itself does not have any asserts. If I understand the question right you should be able to use Iterables.all
assert Iterables.all(balloonsList, isBlue) : "some aren't blue";
Documentation does not clarify whether the predicate is evaluated for rest of elements if one results in false, but I suspect they won't be. You can trivially check the source.
If you do need it to be evaluated for all elements then you should use filter and check the size of the result.