Initialising a variable in the while expression - not the statement - java

In the expression of a while loop, is it possible to initialise a variable, then use that as part of the expression?
It's probably simpler in code:
while (int a = someMethod(), a<b)
It would be possible to just add another method, and so have to following:
private boolean whileLoopTest() {
int a = someMethod();
return a<b;
}
public void originalMethod() {
while (whileLoopTest()) {
//...
but this doesn't seem as neat.
EDIT
I also don't want to directly compare the method to my variable, as it is compared to several variable, and so if would be a long, unreadable mess. A better example of what I want would be:
while (int a = SomeClass.someStaticMethod(), -1<a && a<b)
It's not true in my case, but this would be a equally valid question if someStaticMethod() took a long time to return - I would only want to call it once.
I'm fairly new to StackOverflow, so I'm not sure if giving other situations where this would apply is what I should be doing.

int a;
while((a = someMethod()) < b){
//do something
}
A common use for this is reading from a file:
BufferedReader fileIn = ...
String line;
while((line = fileIn.readLine()) != null){
//do something
}
fileIn.close();
/edit
You can do this for your new scenario:
int a;
while(-1 < (a = SomeClass.staticMethod()) && a < b) {
//do something
}
Once the left hand portion of the && statement is executed, the return value of SomeClass.staticMethod() is stored in a, which carries over the the right hand portion of the statement.

Why not just not assign the value to "a" if you are not using it anyways?
while (someMethod() < b) { doSomething() }
If you actually do need "a" then your alternate solution would not work. The solution then would be either to save it (which I do not consider unneat) or what Kerrek said.

You can use the function directly without using a local variable like this:
while ( someMethod() < b) { /* ... */}
This, if your method returns intended value. (If you are casting it to a local variable, it's supposed to)
EDIT: For your second question.
Your concern is understandable, but if you are assigning that methods value to a local variable inside while loop's boolean expression, in every loop where "While" checks the expression, you are assigning methods' return value to local variable, which means you are calling that method in every iteration. That doesn't change anything from my first answer.

Related

Print all combinations when input is String vs List<String> in Java

Popular problem: print all combinations of input.
Both the first code block and 2nd code block have the same structures. I did debug and track stack, but couldn't understand. That's why I'm posting.
If input is List, the following code works and I understand it.
remain should be backtracked.
ex: input list = ["a", "b", "c"]
public void sublists(List<String> list) {
List<String> chosen = new ArrayList<>();
sublists(chosen, list);
}
private void sublists(List<String> chosen, List<String> remain) {
if(remain.size() == 0) {
System.out.println(chosen);
}
else {
String first = remain.remove(0);
// choose/explore INC. first
chosen.add(first);
sublists(chosen, remain);
// choose/explore EXC first
chosen.remove(chosen.size() -1);
sublists(chosen, remain);
// un-choose for backtracking
remain.add(first);
}
}
However, the same question but different input type, when input is String, doesn't need backtracking of remain in the code below.
Q1: why remain += C; is not reachable in code block below while remain.add(first); is reachable in the code block above even though these two code blocks have the same code structure? In both code block, recursion method get called recursively.
Q2: remain += C; not even needed since it's automatically backed its removed char. Why?
// ex: input s = "abc"
public void combination2(String s) {
combination2Helper("", s);
}
private void combination2Helper(String chosen, String remain) {
if (remain.length() == 0) {
System.out.println(chosen);
}
else {
char C = remain.charAt(0);
chosen += C;
remain = remain.substring(1);
// inc. C + remain w/o C
combination2Helper(chosen, remain);
// exc. C + remain w/o C
chosen = chosen.substring(0, chosen.length() -1 );
combination2Helper(chosen, remain);
// why this backtrack of ramin is not reachable unlike when remain is list
// backtrackig this line is not needed.
remain += C;
}
Besides if the input is string, we don't even need such a long line of code right above.
The following code is working.
Q3: Theoretically we need to backtrack what we've chosen after the recursion call for exhaustive search but why this code doesn't need backtracking of chosen nor remain when the input type is String?
When the input is List, if don't use backtracking, it doesn't work.
I'm confused why the backtracking is not reachable ( not needed ) when input is String while List is needed.
private void combination2Helper(String chosen, String remain) {
if (remain.length() == 0) {
System.out.println(chosen);
}
else {
combination2Helper(chosen, remain.substring(1));
combination2Helper(chosen+remain.charAt(0), remain.substring(1));
}
}
In the list version, you do not need to add C again to the list remain if you copy the list first:
remain = new ArrayList<>(remain);
String first = remain.remove(0);
In the string version, the statement remain += C; will be reached, but it has no real effect, because the value will never be used again. So it can be removed by optimization. The situation is similar to copying the list in the list version. Look at these statements:
char C = remain.charAt(0);
chosen += C;
remain = remain.substring(1);
remain is an argument of the method. This will be assigned with the actual parameter, when the method is called. remain then behaves like a local variable of the method. When a new value is assigned to it inside the method, this will not change the variable passed by the caller (the reference to the string is passed by value).

checking and setting variable, efficiently

I am new to programming and have a simple question: is there a "better" or more efficient way of doing this...
if (x != 0) {
y = x;
}
or
if (getMethod() != null) {
value = getMethod();
}
I'm new to programming and above code (esp the 2nd one) seems inefficient.
Thanks in advance.
You second example can suffer from a "Time of check, to time of use" weakness. If the first invocation of getMethod() returns non-null, it is possible that your second invocation will return null. A better way to do it would be:
value = getMethod();
if(NULL != value)
{
/* use value as planned */
}
else
{
/* handle a null value, probably an error */
}
if interested, you can read more about TOCTTOU weaknesses here.
For your first example, I don't really see a better way of doing this.
N.B. This answer is from the perspective of a C programmer (seeing as how C was one of your tags).
Hope this helps
- T.
You can make it shorter
if ( x ) y = x;
is the same as
if (x != 0) {
y = x;
}
And
if ( getMethod() ) value = getMethod();
is the same as
if (getMethod() != null) {
value = getMethod();
}
First code snippet:
In C any non-zero value is treated as true and 0 treated as false. So, for the first example, you can rewrite it as:
if (x) {
y = x; // this line will be executed if x not equal to zero
}
Second code snippet:
You called getMethod() twice which is not efficient. As per your code, you are assigning the return value of getMethod() into value if getMethod() returns anything but NULL. So you can use a temporary variable to check the return value of getMethod(), like following:
temp = getMethod();
if (temp != null) {
value = temp;
}
That will reduce calling same method twice.

Initializing a class retrieved by a function Java for android

My first question on stackoverflow:
Ok so I am writing a java game for android and I am having trouble with initializing certain classes retrieved from a function/method. Here is my code:
static int unUsedCharacters = 10;
static Character char1;
static Character char2;
static Character char3;
static Character char4;
static Character char5;
static Character char6;
static Character char7;
static Character char8;
static Character char9;
static Character char10;
Character getFreeCharacter() {
if (char1 == new Character()) {
return char1;
} else if (char2 == new Character()) {
return char2;
// and so on... until 10
} else {
return char10;
}
}
public void createCharacter(String x) {
if (unUsedCharacters > 0) {
unUsedCharacters -= 1;
getFreeCharacter() = new Warrior();
//the warrior class extends the character class
} else {
/* no more characters */
}
}
So The problem is where I try to do:
getFreeCharacter() = new Warrior();
It says:
Variable expected.
Any suggestions?
(It is probarly super easy, but this is all new to me)
Thank you for reading/responding
An expression of this form...
(char1 == new Character())
... will always evaluate to false (or throw an exception). The new operator never produces a null result, and it never produces a reference to an object that existed before, but those alternatives cover all the possible values of char1 at any time. More likely you want something like this:
if (char1 == null) {
char1 = new Character();
return char1;
}
In truth, though, I would never hold the ten characters in ten independent variables. I'd probably use a List of Characters, or at worst an array.
Having gotten past that, you have a different problem. The Character you return is already an object assigned to the intended slot. You can set its properties (to the extent that its class allows you to do so), but you cannot replace it with a different object by assigning to it. Indeed, you cannot assign directly to the method result at all, but even if you stored it in a variable, assigning a different object to that variable would not have the effect you want.
(Note, by the way, that I am distinguishing between assigning to members of the method return value, which you can do, and assigning to the value itself, which you cannot do.)
I think you would be best off getting rid of getFreeCharacter() altogether. If you structure your class better then you won't need it. Instead of declaring char1 ... char10 like so:
// Yuck, don't do this
Character char1;
Character char2;
// ...
Character char1;
... do as I suggested earlier and use a List:
import java.util.ArrayList;
import java.util.List;
public MyGame {
List<Character> characters = new ArrayList<>();
// ...
}
Then, your createCharacter() method can have this form:
public void createCharacter(String x) {
if (characters.size() < 10) {
characters.add(new Warrior());
} else {
/* no more characters */
}
}
Elsewhere, you can retrieve elements of the character list via its get() method, e.g. characters.get(0). The List instance takes care of a whole lot of details that you will otherwise have to write your own code for.

Is there any way I can return a value from a loop and continue from where I left off?

Is there any way I can return a value from a loop and continuing from where I left off ?
In the following snippet, I want to return the current value of currVm. But I am unable to do so.
In the innermost loop of the snippet :
while(c <= currVm) {
allocatedVm(currVm);
c++;
}
a function named allocatedVm is called. I want to return the value of currVm and start again from where I left off. Is there any way out ?
#Override
public int getNextAvailableVm() {
Set<String> dataCenters = confMap.keySet();
for (String dataCenter : dataCenters) {
LinkedList<DepConfAttr> list = confMap.get(dataCenter);
Collections.sort(list, new MemoryComparator());
int size = list.size() - 1;
int count = 0;
while(size >= 0) {
DepConfAttr dca = (DepConfAttr)list.get(count);
int currVm = dca.getVmCount();
int c = 0;
while(c <= currVm) {
allocatedVm(currVm); // RETURN currVm
c++;
}
count++;
size--;
}
}
}
The best approach would probably be to write a method returning an Iterable<Integer>. That's not as easy in Java as it is in languages which support generator functions (e.g. C# and Python) but it's still feasible. If the code is short, you can get away with a pair of (nested) anonymous inner classes:
public Iterable<Integer> foo() {
return new Iterable<Integer>() {
#Override public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
// Implement hasNext, next and remove here
};
}
};
}
In your case I'd be tempted to break it into a separate non-anonymous class though, just for simplicity.
Anyway, the point of using Iterable is that an Iterator naturally has state - that's its purpose, basically. So it's a good fit for your requirements.
Another rather simpler approach would be to return all of the elements in one go, and make the caller perform the allocation on demand. Obviously that doesn't work well if there could be a huge number of elements, but it would be easier to understand.
not sure i understand what you need, but:
if you wish to notify the caller of the method that you've got a value during the running of the method, but don't wish to exit the method just yet, you can use listeners.
just create an interface as a parameter to your function, and have a function inside that will have the object as a parameter.
example:
interface IGotValueListener
{
public void onGotValue(MyClass obj);
}
public int getNextAvailableVm(IGotValueListener listener)
{
...
if(listener!=null)
listener.onGotValue(...);
}
now , for calling the method, you do:
int finalResult=getNextAvailableVm(new IGotValueListener ()
{
... //implement onGotValue
};
You can return from anywhere in your method , by just putting the return keyword. If you want to put a functionality to resume ur method from different places then u need to factor ur method in that way. You can use labels and if statements, set some static variables to mark the last execution place. If your application is not multi-threaded then u need not to worry with the use of static variable synchronization. Also if your method is too big and becoming hard to follow/read, then think about breaking it into smaller ones.

Final initialization in java can be postponed, how does this prevent against returning null inadvertently?

In the "hidden features of java" question, someone mentions that final initialization can be postponed and provides an example:
public Object getElementAt(int index) {
final Object element;
if (index == 0) {
element = "Result 1";
} else if (index == 1) {
element = "Result 22";
} else {
element = "Result 3";
}
return element;
}
The poster says:
It's too easy to miss a case and return null by accident. It doesn't make returning null impossible, just obvious that it's on purpose.
However I cannot wrap my head around what this means. How is this any different if element was not declared final? Wouldn't the else statement always ensure that null is not returned? I'm thinking this is more a cosmetic thing rather than actually effecting the way the code operates.
The way you posted the question, the poster seems to be saying that if you did:
Object element = null;
And then set it via the if methods, you could return null by accident (if you didn't construct your else statement correctly), so take advantage of the fact that final initialization can be differed to after declaration.
However, the example is superfluous, because the compiler guarantees that this variable will be set before being used because it is local.
More interesting would be a case like this:
public class SomeClass {
private final Object element;
public SomeClass(int index) {
if (index == 0) {
element = "Result 1";
} else if (index == 1) {
element = "Result 22";
} else {
element = "Result 3";
}
}
}
In that case the compiler will warn you if you never set element, rather than setting it to null for you, which is what would happen if it was not declared final.
In summary, what is interesting to know is that a final field or variable doesn't have to be set where it is declared (as you might be inclined to think). Final means that it can only be set to a given value once, not that it has to be set on the same line as it is declared.
Finals can only be set and never re-set. They are sometimes conflated with the concept of constants in java. More correctly they are immutable object references.
The catch is that if something is immutable, how and when do you set its initial value. The answer is that java checks that only one possible flow can assign a value to a final variable. That way you don't have to assign the value at declaration time.

Categories

Resources