I want to replace nested for loops in the following code with streams:
private boolean check(St st) {
List<Co> prereqs = getCoPrereqs();
for (Co prereq : prereqs) {
List<En> stEns = st.getEns();
boolean flag = false;
for (En en : stEns) {
if (en.getCo().equals(prereq) && en.getGr() != null) {
if (en.hasPassedCo()) {
flag = true;
}
}
if (!flag)
return false;
}
}
return true;
}
The two loops and the variable flag is causing confusion. I am not sure if this can be converted to streams totally.
I have simplified your code somewhat by doing the following:
removing the boolean flag. It isn't necessary.
get the List<En> just one time outside of the Prereq loop. You can reiterate the original as often as necessary.
The major difference is to check for a false return from en.hasPassedCo() and return false immediately. Once the iterations are complete, then return true.
private boolean check(St st) {
List<Co> prereqs = getCoPrereqs();
List<En> stEns = st.getEns();
for (Co prereq : prereqs) {
for (En en : stEns) {
if (en.getCo().equals(prereq) && en.getGr() != null) {
if (!en.hasPassedCo()) {
return false;
}
}
}
}
return true;
}
I'm not certain that streams would improve this (at least not knowing more about the relationships of the fields to each other). Also, it doesn't make sense how Co relates to en.getCo. Seems to me that something like prereqs.contains(en.getCo()) would be more appropriate.
Probably, you can use nested streams with allMatch.
I'm saying "probably" because I can't be sure that the code you've proved does what expected, types name are not self-explanatory at all (names in the code matter a lot) and you have not accompanied the code with any explanations.
If I understood your code correctly, you need to validate every Co object returned by getCoPrereqs() and that entails checking each Co object against En object from a List<En> which should be extracted from the method parameter.
That's how it might look like:
private boolean check(St st){
return getCoPrereqs().stream()
.allMatch((Co prereq) -> st.getEns().stream()
.allMatch((En en) -> en.getCo().equals(prereq)
&& en.getGr() != null
&& en.hasPassedCo()
));
}
For readability reasons (to make it more easier to compare stream with loops), I've used explicitly typed lambda expressions (the common practice is to omit types for brevity and let the type inference do the job).
Related
Currently I am cleaning up hard to maintain and test if else clutter which is based on conditions which have to be checked in isolations:
What is the basic semantic of the conditions?
Big Entity Objects have to be checked based on two entity keys namely Trans and Right for state change as in the example Below:
if (oldTrans.getfOrder().equals(newTrans.getfOrder()) {
compound.setIsStateChanged(true);
return;
}
if (oldRight.getfRight().equals(newRight.getfRight()) {
compound.setIsStateChanged(true);
}
Currently the if else are all cluttered up at one place:
if (oldTrans.getfOrder().equals(newTrans.getfOrder()) {
compound.setIsStateChanged(true);
LOGGER.info("major change detected");
return compound;
} if (oldTrans.getgOrder().equals(newTrans.getgOrder()) {
compound.setIsStateChanged(true);
LOGGER.info("major change detected");
return compound;
}
I see 2 main issues here
Every if has a return statement and with so many ifs it hard to know when and a what point method exits.
To many if branchings are error prone and The number of conditions is likely to go up.
To avoid so many ifs that are basically based on the same semantic underneath from clean code perspective I tried to solve it the polymorphic way
Extracting the Conditions in Enums as Constants and impleneting a checker Interface that takes new and old objects as params
public interface ICheckStateChange<T>(T old, T new) {
boolean check(T old, T new);
}
//implementations
public TransChecker implements ICheckStateChange<Trans> {
List<BiPredicate<Trans, Trans>> allTransConditions = transConditions.getValues();
public boolean check(Trans oldTrans, Trans newTrans) {
//all conditions null check here
//loop through conditions
for (BiPredicate<Trans, Trans> transCondition: allTransConditions) {
if (transCondition).test()) {
return true;
LOGGER.info("major state change detected, taking apt action")
}
}
public RightChecker implements ICheckStateChange<Right> {
List<BiPredicate<Right, Right>> allTransConditions = RightConditions.getValues();
public boolean check(Right oldRight, Right newRIght) {
//all conditions null check here
//loop through conditions
for (BiPredicate<Right, Right> rightCondition: allRightConditions) {
if (rightCondition).test()) {
return true;
LOGGER.info("major state change detected, taking apt action")
}
}
The Conditons are now centrally located as BiPredicate constants using lambdas
public enum rightConditions {
FORDER_CHANGE_NULL_TO_NOT_NULL((Order old, Order new)
-> old == null && new != null),
//to be replaced by the right condition
GORDER_CHANGE_FROM_OPEN_TO_DONE((Order old, Order new)
-> old == null && new != null)
//to be replaced by the right condition
LORDER_CHANGE_FROM_OPEN_TO_REVERTED((Order old, Order new)
-> old == null && new != null)
........
}
My question here is about the approach of refactoring the If elses with the help of lambda BiPredicates in hinddight of clean code? Readability, extensibility and maintainability ;)
Which way of returning from condition is better , Like the process1 and process 2 both does the same. But I want to know better way returning.
In both cases I don't want to enter inside of loop, I just want to return. I would like to know that, Is there any performance difference If I put return before control passes to end. I don't want Java Virtual Machine to check end of loop and returning from there. I thought If I put return Immediately when the condition not satisfied, then I could see minor performance difference and also code readability. Please suggest me the best way.
Let us consider the below scenarios.
Process1:
public Method()
{ //Method
Company company = new Company(); //Object
if (null != Address && null = Address.location()) //Condition
{
return company; //I want to return
}
for (Location location: Address.location())
{
//forloop
}
return company; //return
}
Process2:
public Method()
{
Company company = new Company();
if (null != Address && null != Address.location())
{
//enters loop
}
return company; // return
}
There will be some performance impact. Iterating complete objects from the for loop to verify the condition.
For example:
We can write like this.
if(condition is false){
return ;
else{
for(DataType ref: collection){
if(true){
return;// return from here, so that it will not iterate remaining elements.
}
}
}
ex 2:
if there is a logic after the if and that should not be executed, if the object is null.
if(object is null){
return ;
}
//Remaining logic here will not be executed, if the object is null. it's a good way of writing.
ex 3:
if there is no logic after the if and else, then directly return from the end of method.
if(object is null){
return
}else{
//process logic and return.
}
you can write something like this.
if(object is not null){
// return either from here.
}
return here is also fine...
When adding 'intentions' to PhpStorm (or other JetBrains IDE's), how can I detect whether a PsiElement is a string? I've based my code off the only intention example I could find. I can't seem to find proper documentation. This is as far as I got:
#NonNls public class SomeIntention extends PsiElementBaseIntentionAction implements IntentionAction {
public boolean isAvailable(#NotNull Project project, Editor editor, #Nullable PsiElement element) {
if (element == null || !(element instanceof /* String? */) {
return false;
}
}
}
instanceof String obviously doesn't work, but even using PsiViewer I can't figure out how to test whether it's a string.
I would recommend looking into intellij-community source code, logging, debugging and using PsiViewer plugin, you would then find that PsiJavaToken of certain type contains a String.
The following worked to check if our current node is a string (either double quoted or single quoted):
ASTNode ast_node = element.getNode();
if(ast_node == null) {
return false;
}
IElementType element_type = ast_node.getElementType();
if(element_type != PhpTokenTypes.STRING_LITERAL
&& element_type != PhpTokenTypes.STRING_LITERAL_SINGLE_QUOTE) {
return false;
}
return true;
In my case, I only wanted 'raw strings', not strings with variables or concatenation. If any variables or concatenation signs exist in a string, PSI sees those as separate siblings. So I could find raw strings by ruling out strings with siblings:
// Disregards strings with variables, concatenation, etc.
if (element.getPrevSibling() != null || element.getNextSibling() != null) {
return false;
}
return true;
Often in java I have to get a value of a property of an object which is deep in this object. For example, if I'm sure that all my sub-objects are not null, I can do that :
public function getDeepValue(A a) {
String value = a.getB().getC().getListeD().get(0).getE().getValue();
return value;
}
But in case of sub objects of the parent can be null, I have to test every object.
To do that, I see 2/3 solutions :
First, step by step :
public function getDeepValue(A a) {
if(a == null){
return null;
}
B b = a.getB();
if(b == null) {
return null;
}
C c = b.getC();
if(c == null){
return null;
}
List<D> ds = c.getListeD();
if(ds == null || ds.size() == 0){
return null;
}
D d = ds.get(0);
if(d == null) {
return null;
}
E e = d.getE()
if(e == null){
return null;
}
return e.getValue();
}
Second, test all in one if block, soooo dirty :
public function getDeepValue(A a) {
if(a != null && a.getB() != null && a.getB().getC() != null && a.getB().getC().getListeD() != null && a.getB().getC().getListeD().size() > 0 && a.getB().getC().getListeD().get(0) != null && a.getB().getC().getListeD().get(0).getE() != null){
return a.getB().getC().getListeD().get(0).getE().getValue();
}
return null;
}
Third solution, using a try catch block :
public function getDeepValue(A a) {
try {
return a.getB().getC().getListeD().get(0).getE().getValue();
} catch(NullPointerException e) {
return null;
} catch(IndexOutOfBoundsException e) {
return null;
}
}
Solution 1 seems not too bad but needs a lot of code. It is generally the solution I use.
Solution 2 is for me really dirty...
In paper, I realy like solution 3, but is it a good solution in term of performances ?
Is there any others acceptables solutions ?
Thanks for help, I hope my english is not too bad..
Regards
Solution #3 looks simple, but it can potentially hide a whole host of problems. It might be an adequate solution if you have full access to all of the classes in the chain and you know what's going on in each method and you can guarantee those methods won't cause problems with your try/catch and you're never going to change them... that's a lot of conditions to make it a worthwhile solution, but I can conceive that it's possibly a useful sufficient one.
Solution #2 looks horrid to me, especially if one or more of the get methods is a bottleneck (such as a slow database query or using a blocking network connection). The earlier in the chain such a potential bottleneck, the worse it would potentially be, as you're calling it over and over again. This of course depends on the implementation of the methods in question (even if one of them is slow, the result could be cached, for example), but you shouldn't need to know that in your client code. Even with efficient or trivial implementations, you've still got the overhead of repeated method calls you oughtn't need.
Solution #1 is the best of the three, but it's likely not the best possible. This solution takes more lines of code than the other two, but it doesn't repeat itself and it isn't going to be tripped up by the implementations of the other methods. (Note: If you do not have access to the classes in the chain for refactoring, I would use this solution.)
A better solution than #1 would be to refactor the classes so that the client code doesn't need to know about this chain at all. Something along these lines:
class Client {
public Mumble getDeepValue(A a) { return a == null ? null : a.getDeepValue(); }
}
class A {
private B b;
public Mumble getDeepValue() { return b == null ? null : b.getDeepValue(); }
}
class B {
private C c;
public Mumble getDeepValue() { return c == null ? null : c.getDeepValue(); }
}
class C {
private List<D> ds;
public Mumble getDeepValue() {
D d = ds == null || ds.size() == 0 ? null : ds.get(0);
return d == null ? null : d.getDeepValue();
}
}
class D {
private E e;
public Mumble getDeepValue() { return e == null ? null : e.getMumble(); }
}
class E {
private Mumble m;
public Mumble getMumble() { return m; }
}
As you can see, the longest chain any of these classes has is to access the public members of an element of a collection that is a private member of the class. (Essentially ds.get(0).getDeepValue()) The client code doesn't know how deep the rabbit hole goes, only that A exposes a method which returns a Mumble. Client doesn't even need to know that the classes B, C, D, E, or List exist anywhere!
Additionally, if I were designing this system from the ground up, I would take a good long look at whether it could be restructured such that the actual Mumble object wasn't so deep. If I could reasonably get away with storing the Mumble within A or B, I'd recommend doing it. Depending on the application, that may not be possible however.
in terms of performance solution 3 is the best one. In addition It is neat and easy to understand , For example looking at a loop example:
int[] b = somevalue;
for(int i=0;i<b.length;i++){
//do something
}
in this case for every iteration we execute the condition. However, there is another approach for it which uses try and catch
int[] b = somevalue;
try{
for(int i=0;;i++){
//do something
}
}catch(IndexOutOfBoundException e){
// do something
}
on the second solution,the loop keeps going until we reach the end of the loop which then it throws IndexOutOfBoundException as soon as we reach the end of the array. meaning we don't check for the condition no more. thus faster.
Given the following code snippets, is there any appreciable difference?
public boolean foo(int input) {
if(input > 10) {
doStuff();
return true;
}
if(input == 0) {
doOtherStuff();
return true;
}
return false;
}
vs.
public boolean foo(int input) {
if(input > 10) {
doStuff();
return true;
} else if(input == 0) {
doOtherStuff();
return true;
} else {
return false;
}
}
Or would the single exit principle be better here with this piece of code...
public boolean foo(int input) {
boolean toBeReturned = false;
if(input > 10) {
doStuff();
toBeReturned = true;
} else if(input == 0) {
doOtherStuff();
toBeReturned = true;
}
return toBeReturned;
}
Is there any perceptible performance difference? Do you feel one is more or less maintainable/readable than the others?
With the second example you state very clearly that both conditions are mutually exclusive.
With the first one, it is not so clear, and in the (unlikely) event that an assignment to input is added between both ifs, the logic would change.
Suppose someone in the future adds input = 0 before the second if.
Of course this is unlikely to happen, but if we are talking about maintainability here, if-else says clearly that there are mutually exclusive conditions, while a bunch of ifs don't, and they are not so dependent between each other as are if-else blocks.
edit:Now that I see, in this particular example, the return clause forces the mutual exclusivity, but again, we're talking about maintainability and readability.
Anyway, about performance, if this is coded in Java you shouldn't care for performance of a couple of if blocks, if it were embedded C in a really slow hardware, maybe, but certainly not with java.
Use whatever form best describes your intent.
Do not follow the single exit principle if things are this simple, though--it just makes it more confusing.
In the first:
somebody eventually, by some strange reason and when you're not looking will add some add statement that will make this method fail under certain strange conditions, everybody ( or worst, one single person ) will spend 4 hrs. watching the source code and debugging the application to finally found there was something in the middle.
The second is definitely better, not only it prevents this scenario, but also helps to clearly state , it this or this other no more.
If all the code we write within an if where 10 lines long at most, this wouldn't matter really, but unfortunately that's not the case, there exists other programmers which by some reason think that a if body should be > 200 lines long... anyway.
I don't like the third, it forces me to look for the return variable, and it's easier to find the return keyword
About speed performance, they are ( almost ) identical. Don't worry about that.
In your last example, don't do this:
public boolean foo(int input) {
boolean toBeReturned = false;
if(input > 10) {
doStuff();
toBeReturned = true;
} else if(input == 0) {
doOtherStuff();
toBeReturned = true;
}
return toBeReturned;
}
but this (notice the use of Java's final):
public boolean foo(int input) {
final boolean toBeReturned; // no init here
if(input > 10) {
doStuff();
toBeReturned = true;
} else if(input == 0) {
doOtherStuff();
toBeReturned = true;
} else {
toBeReturned = false;
}
return toBeReturned;
}
By doing so you make your intend clear and this is a godsend for IDEs supporting "programming by intention" (there's no need to "compile" to see potential errors, even on a partial AST, a good IDE can examine incomplete source in real-time and give you instant warnings).
This way you are sure not to forget to initialize your return value. This is great if later on you decide that after all you need another condition.
I do this all the time and even moreso since I started using IntelliJ IDEA (version 4 or so, a long time ago) and this has saved me so many silly distraction mistakes...
Some people will argue that this is too much code for such a simple case but that's entirely missing the point: the point is to make the intent clear so that the code reads easily and can be easily extended later on, without accidentally forgetting to assign toBeReturned and without accidentally forgetting to return from a later clause you may add.
Otherwise, if "conciseness" was the name of the game, then I'd write:
public boolean foo(int a) {
return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false;
}
Where both doStuff and doOtherStuff would return true.
Semantically — no. Performance-wise this depends on compiler, i.e. whether it can spot that both conditions cannot be true at once. I'd bet standard Sun compiler can. Whether to use single exit principle depends on tastes. I personally hate it.
Version #1 and #2 may be faster than #3, but I suppose the performance difference is minimal. I would rather focus on readability.
Personally, I would never use version #2. Between #1 and #3, I would choose the one that yields the most readable code for the case in question. I don't like many exit points in my methods, because it makes the code hard to analyze. However, there are cases where the flow becomes clearer when we exit immediately for some special cases, and continue with the main cases.
Think of this case when the two examples won't be similar:
public boolean foo(int input) {
if (input > 10) {
// doStuff();
return true;
}
System.out.println("do some other intermediary stuff");
if (input == 0) {
// doOtherStuff();
return true;
}
return false;
}
vs.
public boolean foo(int input) {
if (input > 10) {
// doStuff();
return true;
}
//System.out.println("doing some intermediary stuff... doesn't work");
else if (input == 0) {
// doOtherStuff();
return true;
} else {
return false;
}
return false;
}
The first approach is probably more flexible, but both formulas have their use in different circumstances.
Regarding performance, I think the differences are to small to be taken in consideration, for any regular java application, coded by sane programmers :).
In your case the second if would only get called if the first if failed so it's less important here but if your first if did something and didn't return, the second if (which would then always be false) would still be tested unless it was in an else-if.
In other words, there are cases where the difference between if-else-if and if-if matters, but this isn't one of them.
Example: Try this and then try it after removing the else. You get two different outputs:
int someNumber = 1;
if(someNumber < 5)
{
someNumber += 5;
Console.WriteLine("First call.");
}
else if(someNumber >= 5)
{
Console.WriteLine("Second call.");
}
Between the first and second snippets, there's really no difference. However the third snippet is quite inefficient. Because you wait to return control of the program to the caller until the last line of code in the method, you waste processing power/memory whereas the first two code snippets return control as soon as it determines one of the conditions to be true.