Let's say that I have two strings that can be passed as parameter:
String one = "one";
String two = "two";
Which of the following methods would be the most efficiƫnt?
private void exampleOne(String example){
if(example.equals("one"){
// do this
}else{
// do this
}
}
private void exampleTwo(String example){
if(example.equals("one"){
//do this
}else if(example.equals("two"){
// do this
}
}
private void exampleThree(String example){
if(example.equals("one"){
// do this
}
if(example.equals("two"){
// do this
}
}
I would compare the methods for efficiency, if they have the same functionality. Currently, all the 3 methods are functionally different. So, no point is there in comparing them.
exampleOne() - If example is equal to "one", execute if. Execute else for all other values.
exampleTwo() - If example is equal to "one", execute if. Execute else if, if it is equal to "two", else for all other values, do nothing - (Here's one difference).
exampleThree() - Well, this one (as it stands) is more or less same as the 1st one, with one extra comparison, which btw, isn't going to affect much as far as efficiency is concerned. However, there are chances that both the if statements might execute in this method, if in between the two if statements, you assign string "two" to example, which is not possible in exampleOne method. To be more clear, you have two independent if blocks here, while in the first method, it's an if-else block (only one of which will be executed).
The one that, statistically speaking, makes the fewest string compares i.e.
if (example.equals("one"){
// do this
} else {
// do this
}
No one is the most efficient due that you have just two options, you should consider that the value doesn't be not one and not two, maybe other one (empty? null?) SO you should write something like that:
if(example.equals("one"){
//do this 1
}else if(example.equals("two"){
// do this 2
}else{
// do this 3
}
Those blocs can not be compared ans you can not state what is the best of them as they flow is different for each case.
This bloc provide two paths a positive and not.
private void exampleOne(String example){
if("one".equals(example){ //deciosn
// path positive
}else{
// path negative
}
}
This block provide three paths, positive, negative-positive, negative-negative
private void exampleTwo(String example){
if("one".equals(example){
//path positive
}else {
// path negative
if("two".equals(example{
// path negative-positive
}
}
}
This block provide four path, postive, negative and positive negative.
private void exampleThree(String example){
if("pne".equals(example){
// path positive
}
if("two".equals(example){
// path positive
}
}
As you see you have four different piece of code that you should not compare to state what is more efficient.
You should focus on the algorithm behind instead not how do the look.
Tip:
Try to use constant on the left side of compare, so you would avoid problems like dereferences and invalid assign.
I would say the first one, just because it only has to evaluate one expression every time...
In my opinion the second one because there you have direct control on both scenarios. When Sring is "one" and "two".
In exampleOne, the method doens't care if "two" or "three" is passed. It cares only situation if "one" is passed
The first one. Because you don't have to check other condition. In other you to make more operation.
The most efficient: 1, 2, 3.
But If you will have to check if i==0 and you will expect that most of them will be != better write if (i != 0) {} else{} than If (i==0) {...}
Keep everything as simple as possible
I'd say first, because if it just says else with no condition then it won't have to check anything, just go straight into 'else'
Theoretically, the first is most efficient.
Practically, you should go for the second, as it offers better readability and maintainability.
Remember, premature optimization is the root of all evil :)
1) most efficient, but this isn't good for maintainability.
private void exampleOne(String example){
if(example.equals("one"){
// do this
}else{
// do this
}
}
2) second efficient, but it is good for maintainability.
private void exampleTwo(String example){
if(example.equals("one"){
//do this
}else if(example.equals("two"){
// do this
}
}
3) third efficient.
private void exampleThree(String example){
if(example.equals("one"){
// do this
}
if(example.equals("two"){
// do this
}
}
i dont know what are your needs so, here you have mi opinions,
the first one, will ALLWAYS do only one checking.. so in that particular example it will be the one with less COMPARISONS.
the second ONE, will do at worst 2 comparisons 1 for "one" and 1 for "two" but... (there is allways a but) it will not any any job if the string is lets say "three" (in the first example it will go to the else)
the 3 example will do ALWAYS 2 COMPARISONS un less you put returns inside the ifs.
so, my opinion is there is not enough information to say wich one is more optimal.
one adition: you can try, instead of writing endles if... to use a case like this one:
switch (true) {
case example.equals("one"):
break;
case example.equals("two"):
break;
default:
break;
}
Apparently the first method would be the most efficient one compared with the possible values of parameters , since the additional if condition in the other methods is useless and will have nothing to do in your case. (extra condition check ==> lower efficiency)
Related
I am creating a mobile application that updates users with the current score and final score in a football match. I want the textview displaying the score to show only the current or final score.
I am having trouble with the if statement. I need one of the fields to contains something in order for a record to be created so I have:
if (!(et_currentgoals.getText().toString().isEmpty()) || !(et_finalgoals.getText().toString().isEmpty()){
}
Inside this if statement I was another that updates the textview with the correct values. So if the final number of goals was entered, the current goals are discarded. Would the best way be something like this:
if(!(et_finalgoals.getText().toString.isEmpty()){
tv_goals.setText(et_finalgoals.getText().toString();
}else{
tv_goals.setText(et_currentgoals.getText().toString();
}
Does this cover both scenarios or am I missing something?
Having that second if block inside the first will work, but there's a simpler way.
This single if will work.
if (!et_finalgoals.getText().toString.isEmpty()) {
tv_goals.setText(et_finalgoals.getText().toString();
} else if (!et_currentgoals.getText().toString.isEmpty()) {
tv_goals.setText(et_currentgoals.getText().toString();
}
In other words, these two blocks are equivalent
if (a || b) {
if (a) {
// a
} else {
// b
}
}
if (a) {
// a
} else if (b) {
// b
}
If I'm understanding correctly, you are executing additional code inside of that first if statement, after setting the tv_goals text. To do that now, you can just check the text of tv_goals.
if (!tv_goals.getText().toString.isEmpty()) {
// Do additional code
}
If this is the case, it ends up being the same amount of code as your original solution. You should just pick whichever way is more clear to you.
Say, I'm making a simple badugi card game where the Hand is represented by 10 characters in a string. E.g:
2s3h5dQs - 2 of spades, 3 of hearts, 5 of diamonds, Queen of spades
Now, in this badugi card game I want to create two loops where the first loop checks if all the ranks are different(none of them can be the same) and the other loop checks if all the suits are different. If both of these conditions return as true where they all have different ranks and suits, the hand has drawn a badugi(please excuse my lack of terminology where necessary.)
Now, how can I create an efficient loop for such a situation? I was thinking that I could create several if statements as such:
if (hand.charAt(0) != hand.charAt(2) && hand.charAt(0) != hand.charAt(4) && hand.charAt(0) != hand.charAt(6))
if (hand.charAt(2) != hand.charAt(0) && hand.charAt(2) != hand.charAt(4) && hand.charAt(2) != hand.charAt(6))
... and so forth comparing every single index to one another. But this gets tedious and seems very unprofessional. So my question is, how do I write an efficient loop for this scenario? How can I compare/check if there are no matches at these specific index points to one another?
If I haven't explained properly then please let me know.
Please keep in mind, I am not allowed freedom of how to formulate a hand. It has to be in the format above
You are putting your energy into the wrong place.
You do not need to worry about efficiency at all.
Instead, you should worry about creating a clean design (based on reasonable abstractions) and then write code that is super-easy to read and understand.
And your current approach fails both of those ideas; unfortunately completely.
In other words: you do not represent hands and values as characters within a String.
You create a class that abstracts a Card (with its value and face).
And then a "hand" becomes a List / array of such Card objects. And then you can use concepts such as Comparator to compare card values, or you can make use of equals() ...
And even when you wish to keep your (actually over-complex) naive, simple approach of using chars within a string; then you should at least use some kind of looping so that you don't compare charAt(0) against charAt(2); but maybe charAt(i) against charAt(j).
And following your edit and the excellent comment by jsheeran: even when you are forced to deal with this kind of "string notation"; you could still write reasonable code ... that takes such string as input, but transforms them into something that makes more sense.
For example, the Card class constructor could take two chars for suite/value.
But to get you going with your actual question; you could something like:
public boolean isCardDistinctFromAllOtherCards(int indexToCheck) {
for (int i=0; i<cardString.length-1; i+=2) {
if (i == indexToCheck) {
continue;
}
if (cardString.charAt(indexToCheck) == cardString.charAt(i)) {
return false;
}
}
return true;
}
( the above is just an idea how to write down a method that checks that all chars at 0, 2, 4, ... are not matching some index x).
You should really think about your design, like creating Card class etc., but back to the question now, since it's not gonna solve it.
I suggest adding all 4 values to a Set and then checking if size of the Set is 4. You can even shortcut it and while adding this yourSet.add(element) return false then it means there is already that element in the set and they are not unique. That hardly matters here since you only need to add 4 elements, but it may be useful in the future if you work with more elements.
I would advice creating an array with these chars you are referencing just to clean up the fact you are using indices. i.e create a vals array and a suits array.
This would be my suggestion by using a return or break the loop will stop this means when a match is found it wont have to loop through the rest of the elements .. Hope this helps !
private static int check(char[] vals, char[] suits){
int flag;
for(int i=0; i<=vals.length-2;i++){
for(int k=vals.length-1; k<=0;k++){
if(vals[i]==vals[k]){
flag=-1;
return flag;
}
if(suits[i]==suits[k]){
flag=1;
return flag;
}
}
}
return 0;
}
Why not simply iterate over your string and check for same ranks or suits:
public class NewClass {
public static void main(String[] args) {
System.out.println(checkRanks("2s3h5dQs"));
System.out.println(checkSuits("2s3h5dQs"));
}
public static boolean checkRanks(String hand){
List<Character> list = new ArrayList<>();
for (int i = 0; i< hand.length(); i+=2){
if (!list.contains(hand.charAt(i))){
list.add(hand.charAt(i));
}
else{
return false;
}
}
return true;
}
public static boolean checkSuits(String hand){
List<Character> list = new ArrayList<>();
for (int i = 1; i< hand.length(); i+=2){
if (!list.contains(hand.charAt(i))){
list.add(hand.charAt(i));
}
else{
return false;
}
}
return true;
}
}
I have a series of four yes/no choices in four separate dialog boxes, the cumulative results of which will lead to one of twelve separate links (e.g., Yes/Yes/Yes/No -> link A, Yes/No/No/Yes -> link B, etc). The branching logic uses boolean values.
Here's what I have so far...just the first dialog box and printing the results for validation.
public class OutageGuideSelector{
public static void main(String[] args){
boolean contactServerUp;
boolean vistaUp;
boolean stormOutage;
boolean vistaCSUp;
//
int contactServerEntry = JOptionPane.showConfirmDialog(null,
"Is the contact server up", "Please select",
JOptionPane.YES_NO_OPTION);
System.out.println("result from entry " + contactServerEntry);
if(contactServerEntry==1)
contactServerUp = true;
else
if(contactServerEntry==0)
contactServerUp = false;
/* System.out.println(contactServerUp); */
}}
Right now, the results of clicking YES reults in a 0 being returned, NO results in a 1. Is this normal, seems counterintuitive, and there's nothing at docs.oracle.java that shows a clear example of the output values except this which seems to suggest that the public static final int YES_NO_OPTION default in 0.
Additionally, the line System.out.println(contactServerUp); comes back with an error that the field contactServerUp might not have been initialized when I un-comment it, so I can't see if my convert-int-to-boolean is working.
First: It appears that JOptionPane method does not include any boolean returns...except getWantsInput() which returns the value of the wantsInput property...so I assume I'm already being the most efficient I can with this. I'd like to know if there's an easier way.
Second, what am I missing that prevents my console output statement from recognizing the contactServerUp? Where's my misplaced semicolon?
According to the javadoc, when one of the showXxxDialog methods returns an integer, the possible values are:
YES_OPTION
NO_OPTION
CANCEL_OPTION
OK_OPTION
CLOSED_OPTION
You should test against those constants:
contactServerUp = (contactServerEntry == JOptionPane.YES_OPTION);
The value returned by the the JOptionPane dialogs are values defined as constant fields in the class.
Although, indeed, one could assume that 0 means false and 1 means true, the values are more ids for the different buttons a dialog can have.
To know if the user pressed yes or no, you can compare the return value to the constant fields described here. For example, in your case :
contactServerUp = (contactServerEntry == JOptionPane.YES_OPTION);
Since a dialog a JOptionPane can have more than two possible 'answers' a boolean would be a poor representation. You are forgetting about the YES, NO and CANCEL option, or what about just a OK answer.
If it would have been written today, I suspect a Enum would have been used instead of an int.
As for the second question, the compiler does not allow access to uninitialized variables.
When you do the following, there is a chance that the variable might not be initialized:
if(contactServerEntry==1)
contactServerUp = true;
else
if(contactServerEntry==0)
contactServerUp = false;
What if, for example, contactServerEntry == JOptionPane.CLOSED_OPTION? In that case, your boolean value is never initialized.
You need to add an else clause at the end of your if-else chain, or initialize contactServerUp value to a default value in the beginning.
Lots of Java books describe the switch statement as being faster than the if else statement. But I did not find out anywhere why switch is faster than if.
Example
I have a situation I have to choose any one item out of two. I can use either use
switch (item) {
case BREAD:
//eat Bread
break;
default:
//leave the restaurant
}
or
if (item == BREAD) {
//eat Bread
} else {
//leave the restaurant
}
considering item and BREAD is a constant int value.
In the above example which is faster in action and why?
Because there are special bytecodes that allow efficient switch statement evaluation when there are a lot of cases.
If implemented with IF-statements you would have a check, a jump to the next clause, a check, a jump to the next clause and so on. With switch the JVM loads the value to compare and iterates through the value table to find a match, which is faster in most cases.
A switch statement is not always faster than an if statement. It scales better than a long list of if-else statements as switch can perform a lookup based on all the values. However, for a short condition it won't be any faster and could be slower.
The current JVM has two kinds of switch byte codes: LookupSwitch and TableSwitch.
Each case in a switch statement has an integer offset, if these offsets are contiguous (or mostly contiguous with no large gaps) (case 0: case 1: case 2, etc.), then TableSwitch is used.
If the offsets are spread out with large gaps (case 0: case 400: case 93748:, etc.), then LookupSwitch is used.
The difference, in short, is that TableSwitch is done in constant time because each value within the range of possible values is given a specific byte-code offset. Thus, when you give the statement an offset of 3, it knows to jump ahead 3 to find the correct branch.
Lookup switch uses a binary search to find the correct code branch. This runs in O(log n) time, which is still good, but not the best.
For more information on this, see here: Difference between JVM's LookupSwitch and TableSwitch?
So as far as which one is fastest, use this approach:
If you have 3 or more cases whose values are consecutive or nearly consecutive, always use a switch.
If you have 2 cases, use an if statement.
For any other situation, switch is most likely faster, but it's not guaranteed, since the binary-search in LookupSwitch could hit a bad scenario.
Also, keep in mind that the JVM will run JIT optimizations on if statements that will try to place the hottest branch first in the code. This is called "Branch Prediction". For more information on this, see here: https://dzone.com/articles/branch-prediction-in-java
Your experiences may vary. I don't know that the JVM doesn't run a similar optimization on LookupSwitch, but I've learned to trust the JIT optimizations and not try to outsmart the compiler.
So if you plan to have loads of packets memory isn't really a large cost these days and arrays are pretty fast. You also cannot rely on a switch statement to auto generate a jump table and as such it's easier to generate the jump table scenario yourself. As you can see in below example we assume a maximum of 255
packets.
To get the below result your need abstraction.. i'm not going to explain how that works so hopefully you have an understanding of that.
I updated this to set the packet size to 255 if you need more then that you'll have to do a bounds check for (id < 0) || (id > length).
Packets[] packets = new Packets[255];
static {
packets[0] = new Login(6);
packets[2] = new Logout(8);
packets[4] = new GetMessage(1);
packets[8] = new AddFriend(0);
packets[11] = new JoinGroupChat(7); // etc... not going to finish.
}
public void handlePacket(IncomingData data)
{
int id = data.readByte() & 0xFF; //Secure value to 0-255.
if (packet[id] == null)
return; //Leave if packet is unhandled.
packets[id].execute(data);
}
Edit since I use a Jump Table in C++ a lot now i'll show an example of a function pointer jump table. This is a very generic example, but I did run it and it works correctly. Keep in mind you must set the pointer to NULL, C++ will not do this automatically like in Java.
#include <iostream>
struct Packet
{
void(*execute)() = NULL;
};
Packet incoming_packet[255];
uint8_t test_value = 0;
void A()
{
std::cout << "I'm the 1st test.\n";
}
void B()
{
std::cout << "I'm the 2nd test.\n";
}
void Empty()
{
}
void Update()
{
if (incoming_packet[test_value].execute == NULL)
return;
incoming_packet[test_value].execute();
}
void InitializePackets()
{
incoming_packet[0].execute = A;
incoming_packet[2].execute = B;
incoming_packet[6].execute = A;
incoming_packet[9].execute = Empty;
}
int main()
{
InitializePackets();
for (int i = 0; i < 512; ++i)
{
Update();
++test_value;
}
system("pause");
return 0;
}
Also another point i'd like to bring up is the famous Divide and Conquer. So my above 255 array idea could be reduced to no more then 8 if statements as a worst case scenario.
I.e. but keep in mind it get's messy and hard to manage fast and my other approach is generally better, but this is utilize in cases where arrays just won't cut it. You have to figure out your use case and when each situation works best. Just as you wouldn't want to use either of these approaches if you only have a few checks.
If (Value >= 128)
{
if (Value >= 192)
{
if (Value >= 224)
{
if (Value >= 240)
{
if (Value >= 248)
{
if (Value >= 252)
{
if (Value >= 254)
{
if (value == 255)
{
} else {
}
}
}
}
}
}
}
}
At the bytecode level, subject variable is loaded only once into processor register from a memory address in the structured .class file loaded by Runtime,and this is in a switch statement; whereas in an if-statement, a different jvm instruction is produced by your code-compiling DE, and this requires that each variable be loaded in to registers although same variable is used as in next preceeding if-statement. If you know of coding in assembly language then this would be commonplace; although java compiled coxes are not bytecode, or direct machine code, the conditional concept hereof is still consistent.
Well, I tried to avoid deeper technicality upon explaining. I hope I had made the concept clear and demystified. Thank you.
I am making a lottery program where I am asking if basically they would like a quick pick ticket. The numbers for their ticket of course would be random since it is a quick pick but the first four numbers range from 0-9 while the fifth number only goes up to 0-4. I am trying to ask them to input a button such as either "1" for no or "2" for yes if they don't want one then it would skip this step. But I am doing the boolean part incorrectly though. Could someone help me out?
Here is an example
System.out.println("Do you want Quick pick, 1 for no or 2 for yes? The first four numbers is from a separate set of 0 to 9 and the fifth number is from a set of 0 to 4.");
QuickPick=keyboard.nextInt();
if((QuickPick==1)){
return false;
}
if((QuickPick==2)){
return true;
int n = (int)(Math.random()*9+0);
System.out.println("Your QuickPick numbers are: " + kickerNumbers + kickerPowerball);
}
I still haven't gotten around to making the line of code for the final number of 0-4, just the first four numbers, so I haven't forgotten that.
Your code for case 2 immediately does a return true; which ends the method (I assume this is in a method) right then and there. Your other lines don't get execute at all.
Consider using a switch() statement here, it'll make it easier to read:
switch(QuickPick)
{
case 1:
return false;
case 2:
int n = (int)(Math.random()*9+0); // Why is n here? You don't do anything with it?
System.out.println("Your QuickPick numbers are: " + kickerNumbers + kickerPowerball);
return true;
default:
// Uh oh - someone did something bad maybe just return false?
return false;
}
Also your code for case 2 is definitely wrong, you need to generate a total of five numbers, using bounds 0-9 for the first 4 and 0-4 for the last one. You'll want to use Java's Random to do this (not Math.Random) something like:
Random rand = new Random();
int somethingRandom = rand.nextInt(10);
// Will give you an integer value where 0 < val < 10
// You can call rand.nextInt as many times as you want
To avoid doing your homework for you -- I'll follow the typical CS textbook line and say "Implementation left as an exercise."
The code after return true will not be executed - you need to put that prior to the return statement
Like Marvo said, you dropped a brace in your if.
But you also have faulty logic. I'm not quite sure what the purpose of the method you're in is (that returns a boolean value). But your last few lines will never be reached unless the user types in something like 3 or 42.
Assuming the method is supposed to a) Ask if the user wants a Quick Pick b) Calculate the Quick Pick, if desired c) Return true/false depending on whether the Quick Pick happened or not, you should have:
public boolean doQuickPick()
{
System.out.println("Do you want Quick pick, 1 for no or 2 for yes? The first four numbers is from a separate set of 0 to 9 and the fifth number is from a set of 0 to 4.");
QuickPick=keyboard.nextInt();
if((QuickPick==1)){
return false;
}
if((QuickPick==2)){
int n = (int)(Math.random()*9+0);
System.out.println("Your QuickPick numbers are: " + kickerNumbers + kickerPowerball);
return true;
}
}
As a separate issue, it'd be much better style to break that into several methods. boolean yesNoPrompt(String message), generateQuickPick(), etc.
Your question is kind of unclear, so I'm afraid I can't be much more help than that. Do post any clarifications / further questions if you have them.
if((QuickPick==2)){
return true;
int n = (int)(Math.random()*9+0);
System.out.println("Your QuickPick numbers are: " + kickerNumbers + kickerPowerball);
}
In the above copied code from your question, I see that you will be getting compilation errors in your IDE. Your IDE will complain about "Unreachable Code" for the line that is just below the return statement. So, you need to put the return statement at the end of the if block.