CompareTo Method - java

I finally think I found a way to sort my transactions by amount using the if statement but I need a way to indicate when one transaction is less or greater than the other they exchange places.
I have a sample of what I've done so far and not too sure what I am missing out here.
#Override
public int compareTo(Student_Transaction Tra)
{
if (getAmount() == ((Student_Transaction) Tra).getAmount()) {
return Amount - Tra.getAmount();
}
else if (getAmount() > ((Student_Transaction) Tra).getAmount()) {
return 1;
}
else if (getAmount() < ((Student_Transaction) Tra).getAmount()) {
return -1;
}
return Amount;
}

This is compareTo method of Student_Stransaction, so no need to use getters:
#Override
public int compareTo(Student_Transaction Tra) {
return Tra != null ? Float.compare(amount, Tra.amount)) : 1;
}

I'd suggest you go with:
return Double.compare(this.amount, tra.getAmount());
which means, you can avoid having to do all those if/else if conditions.

I literally realised that what I did in the thread above was the answer to my question, it clearly defined how I will sort my amounts in each transaction object the final fold of this stage was to use the collection.sort method and in one of the recent threads I have posted the answer to how it is done...
#Override
public int compareTo(Student_Transaction Tra){
if (Tra.getAmount() < getAmount()) {
return -1;
}
else if (Tra.getAmount() == getAmount()) {
return 0;
}
else {
return 1; // Tra.getAmount() > getAmount()
}
}
I didn't need to go the extra mile, ya boy just is misunderstood with his programming and I'm much appreciated with have this community of professional programmers dedicating their time to help people like me out :)

Related

Conditional ternary without else

I have read the similar question and learnt that it is not possible to use a ternary operation instead of if statement, which does not have else statement. Because, if-without else statements are binary not ternary. My question is more best-practice.
In my code, there are lots of code snippet like that
if( calculation < 1 ){
calculation= 0;
}
I would like to shorten these with tenary. Is it a good practice to change these statements with the following.
calculation = calculation < 1 ? 0 : calculation;
You could create a class (or classes) that would create a nice fluent API. Such that your line would be:
calculationTo = replace(calculationTo).with(0).when(calculationTo < 1)
In my opinion it doesn't read much better than a standard if statement, but it also depends on the conditions that you have.
Example implementation:
public class Replacer<T> {
private final T value;
private T replacementValue;
private Replacer(T value) {
this.value = value;
}
public static <V> Replacer<V> replace(V value) {
return new Replacer<V>(value);
}
public Replacer<T> with (T replacementValue) {
this.replacementValue = replacementValue;
return this;
}
public T when(boolean condition) {
if (condition) {
return replacementValue;
} else {
return value;
}
}
}
import static somepackage.Replacer.replace;
public class Main {
public static void main(String[] args) {
int calculationTo = 3;
calculationTo = replace(calculationTo).with(0).when(calculationTo < 1);
}
}
You might expand it or make condition a function so it can be used with lambda, etc. I would also make method with return object of different class (e.g. ReplacerWithValue) so that calling with twice in one chain would result in compilation error.
Since you're asking for a best practice, I'll point out something where you could do better and then I'll tell you why I like the ternary operator.
Let me rephrase you're code snippet:
if (calculatedValueAfterStep1 < 1) {
calculatedValueAfterStep2 = 0;
} else {
calculatedValueAfterStep2 = calculatedValueAfterStep1;
}
When you read your code and somebody asks you "what does 'calculation' represent?" then you cannot answer this question without asking for the line number. The meaning of "calculation" changes over the course of the program code. If you cannot explain what a variable means, you cannot give it a good name. This is why I like my Version better. There is a clear Definition of what meaning the variables "calculatedValueAfterStep1" and "calculatedValueAfterStep2" are. Yes, the names are bad. Change them to your domain accordingly.
Now when you look at the code, you'll notice that "calculatedValueAfterStep2" is not declared. So let's Change the code:
int calculatedValueAfterStep2 = -1;
if (calculatedValueAfterStep1 < 1) {
calculatedValueAfterStep2 = 0;
} else {
calculatedValueAfterStep2 = calculatedValueAfterStep1;
}
Now it gets ugly. The same person asking the earlier question will now ask "why is 'calculatedValueAfterStep2' initialized with '-1'?". So here comes the ternary operator:
int calculatedValueAfterStep2 = (calculatedValueAfterStep1 < 1) ? 0 : calculatedValueAfterStep2;
beautiful!

Turning a for loop to recursive method for prime numbers

I need to convert the code below to a recursive method without using global variables and using only one parameter.I Searched the topics already there is no code with one parameter and doesnt use the global variables.
public boolean isPrime(int x){
for(int i=2;i<x;i++)
if(x%i==0) return false ;
return true;
}
Ok, as for your requirements:
Without using global variables.
Using only one parameter.
And, based on:
it come up in one of my university exams
There a couple of aspects to take into account:
If you pass an instance of a Class you are passing only one variable, and as Classes can have multiple variables inside...
They do not state if you can call multiple functions inside, so, again, this is a hint or clue, of what can you do. So, two solutions for you:
Solution 1 (Using Classes)
class RecursVar {
int x;
int i = 2;
RecursVar(int x) {
this.x = x;
}
}
public boolean isPrimeRecurs(int x){
return isPrime(new RecursVar(x));
}
boolean isPrime(RecursVar recursVar) {
if(recursVar.x % recursVar.i == 0)
return false;
if (++recursVar.i >= recursVar.x)
return true;
return isPrime(recursVar);
}
Solution 2 (Cleaner approach without using Classes but based in that the function that can have only one parameter is isPrime )
boolean isPrime(int x) {
return checkForPrime(x, 2);
}
boolean checkForPrime(int x, int i) {
if (i >= x) return true;
if (x % i == 0) return false;
return checkForPrime(x, ++i);
}
Again, this solutions are based on that many exams require a little creativity and maybe that was the aim of this case.
This cases should not be used in production, they are slow and
prune to make honor to this site (StackOverFlow) with a sweet
java.lang.StackOverflowError
It's an interesting problem.
If you can use java 8, you can solve the problem as followed (note that the case isPrime(2) needs to be checked with an additional if condition):
package test;
import java.util.function.Function;
public class Test {
public static void main(String[] args) {
System.out.println(isPrime(13));
}
private static Function<Integer, Boolean> fun;
public static boolean isPrime(int x) {
fun = i -> {
if (i > 2) return (x%i != 0) && fun.apply(i-1);
else return (x%i != 0);
};
return fun.apply(x-1);
}
}
One of my schoolmates' topic accually recieve a solution here it is if you interested its quite brilliant
https://stackoverflow.com/questions/35660562/finding-prime-numbers-recursively-with-using-only-one-parameter?noredirect=1#comment59001671_35660562

using recursion to add to a variable

below the code is using a private method to add to the variable count. Below that variable are conditionals which by my understanding, will not run until the recursion stack traces upword. Am I correct? My test is failing, and I am trying to see if it is because my code is wrong or I'm using recursion wrong.
public boolean containsRightRedEdge() {
int count = 0;
count += containsRightRedEdge(root);
if(count > 0) return true;
return false;
}
private int containsRightRedEdge(Node n) {
if (n == null) return 0;
if (isRed(n.right)) {
return 1;
}
return containsRightRedEdge(n.left) + 0 + containsRightRedEdge(n.right);
}
I would say you are using recursion pretty much correctly, but your choice of method names could be less confusing, and your logic could be simplified.
I am not too familiar with the algorithm you're trying to implement, but you might try something like this:
public boolean containsRightRedEdge(Node root) {
return getNumRightRedEdges(root) > 0;
}
private int getNumRightRedEdges(Node n) {
if (n == null) return 0;
if (isRedEdge(n)) return 1;
return getNumRightRedEdges(n.left) + getNumRightRedEdges(n.right);
}
Generally a recursive method shouldn't have the same name as a non-recursive method. These method names communicate more clearly what each one does. Also your base cases might be wrong as you've got them written currently based on how I'm interpreting the algo should work. Of course, I don't know the code inside isRed() so I'm probably making wrong assumptions here.
The code above in my question, is the correct way to use recursion in this instance. I just had a typo which is now resolved. Leaving the question for other peoples reference.

Replacing if else with OO aproach

Lets say I have:
if (count <= instance.getFCount()) {
//do something and return String
} else if (count <= instance.getFSCount()) {
//do something and return String
} else if (count <= instance.getTCount()) {
//do something and return String
} else if (count <= instance.getOCount()) {
//do something and return String
}
I am thinking how can I replace this code into something more object oriented. The problem is that if I would have statement like this:
if (count <= 0) {
//do something and return String
} else if (count <= 1) {
//do something and return String
} else if (count <= 2) {
//do something and return String
} else if (count <= 3) {
//do something and return String
}
I could replace it with some factory pattern or enum based approach because my values 0, 1, 2, 3 would always be static. For e.g. I would create a map to hold the class against the number, then if my count is 0 I would know that I need to create an instance from the class which was mapped with zero and so on.
But now I am thinking if there is any way to be done if I don't have the static values in if condition, because for e.g. what is returned to this: instance.getOCount() might be different depending on the configuration.
Could you give me some thoughts how to achieve this?
When you have lots of different if else statements, you can employ a Strategy Pattern. This helps you create manageable code that conforms to the best practice.
I believe there's no need to replace such a simple logic with a design pattern, it's not justified. A switch would be an improvement (assuming count is an integer), but why create a bunch of classes? it'd be justified only if each one had additional, different behavior.
If you use a NavigableMap such as a TreeMap, the keys being your thresholds and values being Callables, you'll be able to retrieve the appropriate Callable and invoke it, all in a one-liner. The relevant method is NavigableMap#ceilingEntry.
final NavigableMap<Integer, Callable<String>> strats = new TreeMap<>();
...
return strats.ceilingEntry(val).getValue().call(args);
I don't think using patterns is the solution here...everything will be harder to read than your original code. But if you are sure, this is one option:
Lets say your instance belongs to a class User. Create an interface
public interface IDynamicAction<T> {
boolean select(T t);
String action(T t);
}
Make a list
List<IDynamicAction<User>> actions = new ArrayList<IDynamicAction<User>>();
actions.add(new IDynamicAction<User>() {
#Override
public boolean select(User instance) {
return count <= instance.getFSCount();
}
#Override
public String action(User t) {
System.out.println("count <= instance.getFSCount()");
return "count <= instance.getFSCount()";
}
});
actions.add(new IDynamicAction<User>() {
#Override
public boolean select(User instance) {
return count <= instance.getTCount();
}
#Override
public String action(User t) {
System.out.println("count <= instance.getTCount()");
return " count <= instance.getTCount()";
}
});
actions.add(new IDynamicAction<User>() {
#Override
public boolean select(User instance) {
return count <= instance.getOCount();
}
#Override
public String action(User t) {
System.out.println("count <= instance.getOCount()");
return " count <= instance.getOCount()";
}
});
And execute your code with
for(IDynamicAction<User> action : actions){
if(action.select(instance)){
String s = action.action(instance);
System.out.println(s);
break;
}
}
Notice the break, I'm assuming based in your code only one action can execute
If you don't need a return value you may use an abstract class instead of an interface and make the if(select) action(); a part of the AbstractDynamicAction class the code will be nicer
Java7 does not really help doing that kind of stuff. Closures would make this things easier on the eye...but IMHO, your original multiple IF is the way to go.

Java - Better idiom for my control flow

I'd like to call a method that either returns false, or an integer. At the moment my code is:
int winningID = -1;
if((ID = isThereAWinner()) != -1) {
// use the winner's ID
} else {
// there's no winner, do something else
}
private int isThereAWinner() {
// if a winner is found
return winnersID;
// else
return -1;
}
I don't like the if((ID = isThereAWinner()) != -1) bit as it doesn't read very well, but unlike C you can't represent booleans as integers in Java. Is there a better way to do this?
I would use something similar to Mat's answer:
class Result {
public static Result withWinner(int winner) {
return new Result(winner);
}
public static Result withoutWinner() {
return new Result(NO_WINNER);
}
private static final int NO_WINNER = -1;
private int winnerId;
private Result(int id) {
winnerId = id;
}
private int getWinnerId() {
return winnerId;
}
private boolean hasWinner() {
return winnerId != NO_WINNER;
}
}
This class hides the implementation details of how you actually represent if there were no winner at all.
Then in your winner finding method:
private Result isThereAWinner() {
// if a winner is found
return Result.withWinner(winnersID);
// else
return Result.withoutWinner();
}
And in your calling method:
Result result = isThereAWinner();
if(result.hasWinner()) {
int id = result.getWinnerId();
} else {
// do something else
}
It may seem a little bit too complex, but this approach is more flexible if there would be other result options in the future.
What about something like:
private int getWinnerId() {
// return winner id or -1
}
private boolean isValidId(int id) {
return id != -1; // or whatever
}
int winnerId = getWinnerId();
if (isValidId(winnerId)) {
...
} else {
...
}
This is all quite subjective of course, but you usually expect an isFoo method to provide only a yes/no "answer".
The problem is you are trying to return two values at once. The approach you have taken is the simplest for this. If you want a more OO or design pattern approach I would use a listener pattern.
interface WinnerListener {
void onWinner(Int winnerId);
void noWinner();
}
checkWinner(new WinnerListener() {
// handle either action
});
private void checkWinner(WinnerListener wl) {
// if a winner is found
wl.onWinner(winnersID);
// else
wl.noWinner();
}
This approach works well with complex events like multiple arguments and multiple varied events. e.g. You could have multiple winners, or other types of events.
I'm afraid not. To avoid errors caused by mistaking if(a == b) for if(a = b), Java removes the conversion between boolean type and number types. Maybe you can try exceptions instead, but I think exception is somewhat more troublesome. (My English is not quite good. I wonder if I've made it clear...)
Perhaps you may wish to consider exceptions to help you with your understanding of asthetics of coding.
Use Integer instead of int and return null instead of -1. Look from this point: "I am returning not integer, but some object that represents winner identity. No winner - no instance"
Joe another suggestion, this is constructed based on #Mat and #buc mentioned little while ago, again this is all subjective of course I'm not sure what the rest of your class/logic is. You could introduce an enum with different ResultStatuses if it makes sense within the context of your code/exmaple.
As Matt mentioned you would expect isValid method to return a boolean yes/no (some may also complain of readability)
public enum ResultStatus {
WINNER, OTHER, UNLUCKY
}
This could be an overkill as well and depends on the rest of your logic (and if logic is expanding) but I thought I'll suggest nonetheless my two cents! So therefore in your public class (similar to #bloc suggested) you could have a method such as below that will return the status of the result checked.
public ResultStatus getResultStatus() {
if (isWinner()) {
return ResultStatus.WINNER;
} else {
return isOtherCheck() ? ResultStatus.OTHER : ResultStatus.UNLUCKY;
}
}

Categories

Resources