Why doesn't Integer.parseInt("1")++ work in Java? - java

I've got the following line of code:
suffix = suffix.isEmpty() ? "1" : Integer.toString(Integer.parseInt(suffix)+1);
in a block where suffix has already been declared as an empty String (""). The block is looking for duplicate file names and adding a number on to any duplicates so they don't have the same name any more.
The line of code above compiles fine, but if I change it to this,
suffix = suffix.isEmpty() ? "1" : Integer.toString(Integer.parseInt(suffix)++);
I get Invalid argument to operation ++/--. Since Integer.parseInt() returns and int, why can't I use the ++ operator?

The ++ operator should update the value of its argument, so the argument should have a fixed position in memory to be updated. For this reason, the argument should be a variable*. In this case, the argument is Integer.parseInt(suffix), has no fixed memory address to be updated at all.
Intuitively, Integer.parseInt(suffix)++ is roughly equivalent to Integer.parseInt(suffix) = Integer.parseInt(suffix) + 1. But Integer.parseInt(suffix) is just an integer value, not associated to a fixed position in memory, so the code above is almost the same thing of, let us say, 32 = 32 + 1. Since you cannot assign a new value to 32 (neither to Integer.parseInt(suffix)) then there is no sense in supporting the ++ operator.
The good news is that this does not cause any problems at all! Instead of Integer.parseInt(suffix)++, write Integer.parseInt(suffix)+1.
* Or, as it is most commonly called, an l-value, or an address value.

++ requires an lvalue (an assignable value).
Integer.parseInt(suffix) is not an lvalue.
Note that i++ is not the same as i+1.

Writing i++ is a shortcut for i=i+1; if you were to 'read it in english' you'd read it as "i becomes current value of i plus one"
which is why 3++ doesn't make sense you can't really say 3 = 3+1 (read as 3 becomes current value of 3 plus one) :-)

The int is an rvalue. Since it isn't bound to a variable you cannot use post-incrementation.

++ expects an assignable value, i.e. a variable. Integer.parseInt returns a value that cannot be assigned. If you need a value plus one, use Integer.parseInt(suffix)+1 instead.

Related

hashmap.get() == operator returning false

I'm working on the following problem:
Gary is an avid hiker. He tracks his hikes meticulously, paying close attention to small details like topography. During his last hike he took exactly n steps.
For every step he took, he noted if it was an uphill, U, or a downhill, D step. Gary's hikes start and end at sea level and each step up or down represents a 1 unit change in altitude. We define the following terms:
A mountain is a sequence of consecutive steps above sea level, starting with a step up from sea level and ending with a step down to sea level.
A valley is a sequence of consecutive steps below sea level, starting with a step down from sea level and ending with a step up to sea level.
Given Gary's sequence of up and down steps during his last hike, find and print the number of valleys he walked through.
For example, if Gary's path is s = [DDUUUUDD], he first enters a valley 2 units deep. Then he climbs out an up onto a mountain 2 units high. Finally, he returns to sea level and ends his hike.
Function Description
Complete the countingValleys function in the editor below. It must return an integer that denotes the number of valleys Gary traversed.
countingValleys has the following parameter(s):
n: the number of steps Gary takes
s: a string describing his path
Input Format
The first line contains an integer , the number of steps in Gary's hike.
The second line contains a single string , of characters that describe his path.
Output Format
Print a single integer that denotes the number of valleys Gary walked through during his hike.
Sample Input
8
UDDDUDUU
Sample Output
1
Below is my implementation in java. It works for the small test cases but not for the big ones.
static int countingValleys(int n, String s) {
//Use a hashmap to keep track of the number of moves.
HashMap<Character,Integer> map = new HashMap();
boolean sea = true;//check if we are at sea level
//if both D and U have the same total no, we are at sea level.
map.put('D',0);
map.put('U',0);
int valleys = 0;//count num of valleys
for(int i = 0; i < n; i++){
char key = s.charAt(i);
//check if we are at sea level
if(map.get('D') == map.get('U')){//<--PROBLEM
sea = true;
}
else
sea = false;
if(sea == true && key == 'D'){//if we are at sea level and our next key is D, we have a valley
valleys += 1;
}
map.put(key,map.get(key) + 1);//add move and update our hashmap
}
return valleys;
}
The problem seems to be at "if(map.get('D') == map.get('U'))", it seems to be returning false for big numbers, can someone tell me why? It works if I assign each map.get() to a variable and compare the variables instead.
I also wrote the exact same thing in javascript using the "new Object()" type and it passed all the test cases, but it is not working in java with hashmap, why is that?
link to original problem - https://www.hackerrank.com/challenges/counting-valleys/problem?h_l=interview&playlist_slugs%5B%5D=interview-preparation-kit&playlist_slugs%5B%5D=warmup
First, as mentioned in other answer, use .equals() instead of == in this case. An even better approach is, you don't even need to use a Map. Just one integer will be good enough.
As your question is ...returning false for big numbers, can someone tell me why?
Here is the reason.
There are several things you need to understand
1. Types of variable
First, you need to know there are two types of variable in Java: Primitive and Reference.
An integer is usually a Primitive, so the variable itself is the integer value: int a = 1234; : a itself is having value 1234.
To compare primitive variable, you should use ==
For reference type, variable itself is a "pointer". In Java there are Wrapper Classes for primitives. For example, Integer is the wrapper for int. So in Integer a = new Integer(1234);, a is not containing value of 1234. It is a pointer pointing to an Integer object reference. Using == on reference type variables does not compare the content, but only check if the pointer value is the same (i.e. check if they point to same object instance)
2. Autoboxing
Starting from Java 1.5 (iirc), there is a feature called auto-boxing (and unboxing), which ease programmer in converting between primitive types and their corresponding wrapper.
In the past, you need to do something like this:
int a = 1234;
Integer intWrapper = new Integer(a);
int b = intWrapper.intValue();
With autoboxing, you just need to write:
int a = 1234;
Integer intWrapper = a;
int b = intWrapper;
And compiler is going to convert it to:
int a = 1234;
Integer intWrapper = Integer.valueOf(a);
int b = intWrapper.intValue();
So far so good?
Final Answer
So the reason why your code works with small number is:
Integer.valueOf() is caching frequently-used value. From API doc:
public static Integer valueOf(int i)
Returns an Integer instance representing the specified int value. If a new Integer instance is not required, this method should generally be used in preference to the constructor Integer(int), as this method is likely to yield significantly better space and time performance by caching frequently requested values. This method will always cache values in the range -128 to 127, inclusive, and may cache other values outside of this range.
Because it is caching the wrappers, therefore if you are doing map.put(key,map.get(key) + 1), result of get(key) + 1, which is an int, when converting to Integer and if it is a small number, will be a same instance of Integer for same int value. That means, == still works (as variables are pointing to same Integer). However if it is a not-cached number, every invocation will be a different instance, and == will not work (as variables are pointing to different instances of Integer, though the value in the Integer instances are the same)
Suggestion to your algorithm, though a bit off topic:
Your logic is over complicated. It can be greatly simplified to (pseudo code):
countValley(String s) {
currentLevel = 0
valleyCount = 0
for (step in s) {
if step == 'U' {
++currentLevel;
if (currentLevel == 0) { // returning to sea level
++valleyCount
}
} else if step == 'D' {
--currentLevel;
}
}
return valleyCount
}
to compare wrapper Class need to use .equals.
can use Objects.equals :
java.util.Objects.equals(firstInteger, secondInteger);
for case above :
if(java.util.Objects.equals(map.get('D'), map.get('U'))){
sea = true;
}
First, don't use '=='. Use .equals for all classes extends Object.
to compare content of wrapper classes (Integer, Float, Long, Double), use .equals(). "==" would compare the references of both objects. The references might be different even though both contain the same content. You will can however use "==" when you are comparing value types such as int, float, long, double.
Solution 1: If you must use a HashMap, looks like iteration in HashMap is the problem. Below a link to how to do it. As you iterate, build your logic for counting hills and valleys. How to efficiently iterate over each entry in a Java Map?.
Solution 2: Use Array instead of HashMap. After building it, find the D sequences and so on.

How many objects are created by using the Integer wrapper class?

Integer i = 3;
i = i + 1;
Integer j = i;
j = i + j;
How many objects are created as a result of the statements in the sample code above and why? Is there any IDE in which we can see how many objects are created (maybe in a debug mode)?
The answer, surprisingly, is zero.
All the Integers from -128 to +127 are pre-computed by the JVM.
Your code creates references to these existing objects.
The strictly correct answer is that the number of Integer objects created is indeterminate. It could be between 0 and 3, or 2561 or even more2, depending on
the Java platform3,
whether this is the first time that this code is executed, and
(potentially) whether other code that relies on boxing of int values runs before it4.
The Integer values for -128 to 127 are not strictly required to be precomputed. In fact, JLS 5.1.7 which specified the Boxing conversion says this:
If the value p being boxed is an integer literal of type int between -128 and 127 inclusive (§3.10.1) ... then let a and b be the results of any two boxing conversions of p. It is always the case that a == b.
Two things to note:
The JLS only requires this for >>literals<<.
The JLS does not mandate eager caching of the values. Lazy caching also satisfies the JLS's behavioral requirements.
Even the javadoc for Integer.valueof(int) does not specify that the results are cached eagerly.
If we examine the Java SE source code for java.lang.Integer from Java 6 through 8, it is clear that the current Java SE implementation strategy is to precompute the values. However, for various reasons (see above) that is still not enough to allow us to give a definite answer to the "how many objects" question.
1 - It could be 256 if execution of the above code triggers class initialization for Integer in a version of Java where the cache is eagerly initialized during class initialization.
2 - It could be even more, if the cache is larger than the JVM spec requires. The cache size can be increased via a JVM option in some versions of Java.
3 - In addition to the platform's general approach to implementing boxing, a compiler could spot that some or all of the computation could be done at compile time or optimized it away entirely.
4 - Such code could trigger either lazy or eager initialization of the integer cache.
First of all: The answer you are looking for is 0, as others already mentioned.
But let's go a bit deeper. As Stephen menthioned it depends on the time you execute it. Because the cache is actually lazy initialized.
If you look at the documentation of java.lang.Integer.IntegerCache:
The cache is initialized on first usage.
This means that if it is the first time you call any Integer you actually create:
256 Integer Objects (or more: see below)
1 Object for the Array to store the Integers
Let's ignore the Objects needed for Store the Class (and Methods / Fields). They are anyway stored in the metaspace.
From the second time on you call them, you create 0 Objects.
Things get more funny once you make the numbers a bit higher. E.g. by the following example:
Integer i = 1500;
Valid options here are: 0, 1 or any number between 1629 to 2147483776 (this time only counting the created Integer-values.
Why? The answer is given in the next sentence of Integer-Cache definition:
The size of the cache may be controlled by the -XX:AutoBoxCacheMax= option.
So you actually can vary the size of the cache which is implemented.
Which means you can reach for above line:
1: new Object if your cache is smaller than 1500
0: new Objects if your cache has been initialized before and contains 1500
1629: new (Integer) - Objects if your cache is set to exactly 1500 and has not been initialized yet. Then Integer-values from -128 to 1500 will be created.
As in the sentence above you reach any amount of integer Objects here up to: Integer.MAX_VALUE + 129, which is the mentioned: 2147483776.
Keep in mind: This is only guaranteed on Oracle / Open JDK (i checked Version 7 and 8)
As you can see the completely correct answer is not so easy to get. But just saying 0 will make people happy.
PS: using the menthoned parameter can make the following statement true: Integer.valueOf(1500) == 1500
The compiler unboxes the Integer objects to ints to do arithmetic with them by calling intValue() on them, and it calls Integer.valueOf to box the int results when they are assigned to Integer variables, so your example is equivalent to:
Integer i = Integer.valueOf(3);
i = Integer.valueOf(i.intValue() + 1);
Integer j = i;
j = Integer.valueOf(i.intValue() + j.intValue());
The assignment j = i; is a completely normal object reference assignment which creates no new objects. It does no boxing or unboxing, and doesn't need to as Integer objects are immutable.
The valueOf method is allowed to cache objects and return the same instance each time for a particular number. It is required to cache ints −128 through +127. For your starting number of i = 3, all the numbers are small and guaranteed to be cached, so the number of objects that need to be created is 0. Strictly speaking, valueOf is allowed to cache instances lazily rather than having them all pre-generated, so the example might still create objects the first time, but if the code is run repeatedly during a program the number of objects created each time on average approaches 0.
What if you start with a larger number whose instances will not be cached (e.g., i = 300)? Then each valueOf call must create one new Integer object, and the total number of objects created each time is 3.
(Or, maybe it's still zero, or maybe it's millions. Remember that compilers and virtual machines are allowed to rewrite code for performance or implementation reasons, so long as its behavior is not otherwise changed. So it could delete the above code entirely if you don't use the result. Or if you try to print j, it could realize that j will always end up with the same constant value after the above snippet, and thus do all the arithmetic at compile time, and print a constant value. The actual amount of work done behind the scenes to run your code is always an implementation detail.)
You can debug the Integer.valueOf(int i) method to find out it by yourself.
This method is called by the autoboxing process by the compiler.

Variable expected [duplicate]

This question already has answers here:
Why doesn't the post increment operator work on a method that returns an int?
(11 answers)
Closed 5 years ago.
private void calculateForEachQuestion() {
...
if (questions.size() >= answers.size()) {
answers.forEach(answer -> {
if (questions.contains(answer))
this.answer.setPoints((this.answer.getPoints())++);
// Variable expected ^
});
}
The error I encountered is:
unexpected type
required: variable
found: value
What is wrong with the statement?
this.answer.setPoints((this.answer.getPoints())++);
The ++ operator only makes sense when applied to a declared variable.
This operator will add one to an integer, long, etc. and save the result to the same variable in-place.
If there is no declared variable, there is nowhere to save the result, which is why the compiler complains.
One way to allow use of the ++ operator in this situation would be (not the most concise code, but to illustrate the point):
int myVariable = this.answer.getPoints();
myVariable++;
this.answer.setPoints(myVariable);
this.answer.getPoints() will return a value, and you can't use increment ++ or decrement -- on that. You can only use it on variables.
If you want to add 1 to it, you can do it as:
this.answer.setPoints((this.answer.getPoints())+1);
I know that, but why?
You can do this:
int x = 5;
x++; // x is a variable and can have value 6
but not this:
5++; // 5 is a value and can't have value 6
Change this:
this.answer.setPoints((this.answer.getPoints())++);
to:
this.answer.setPoints((this.answer.getPoints())+1);
++ will increment a variable with 1, but since this.answer.getPoints() will return a value and its not a defined variable, it won't be able to store the incremented value.
Think of it like doing:
this.answer.getPoints() = this.answer.getPoints() + 1, where would the incremented value be stored?
The error is just in this bit:
(this.answer.getPoints())++
The first part of this (this.answer.getPoints()) creates an rvalue: effectively, an anonymous variable that lasts almost no time.
The second part ++ increments that anonymous variable after it is passed into setPoints().
Then, the anonymous variable (now incremented) is thrown away.
The compiler/IDE knows that you're doing something that will never be used (incrementing a temporary value), and is flagging it.

The Swedish Chef Translator

So the context is, I have a CS project where input is taken in either word or sentence form, and then it is translated to what The Swedish Chef from The Muppets would say. I decided to take the input as one line of string, and send that line into a parser, which in turn would build an array out of translations of the input's letters. The conditions for what gets changed are defined within. the current error I am getting: (while using "INPUT" as input)
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 3, Size: 1
at java.util.ArrayList.rangeCheckForAdd(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at SwedishTranslator.parseString(SwedishTranslator.java:62)
at SwedishTranslator.main(SwedishTranslator.java:12)
Currently it is supposed to just print the array, I wanted to worry about formatting after the fact.
The code:
Sorry for the walls of text but I can't find where the issue is exactly and I figured I would give it a shot here. Thanks in advance.
ind<=in.length() goes one step too far.
Use ind < in.length() or ind <= in.length() - 1
The error arrises on line 62 which I assume is in your big if else section.
Within there you have several ind++ calls. This increments the pointer you use in the loop. So if your code must go through several of these statements it will go beyond the array index.
Additionally you have an issue in the for loop as joval mentioned
Edit
The ++ unary operator increments the variable (-- decrements). Placing the ++ after the variable name (x++) will increment before evaluation, where ++x will increment after evaluation.
This is a common test question for CS students so I suggest you do some more research and practice regarding the operator.
You're making a couple of really understandable beginner mistakes here. Instead of explicitly fixing your code, I'll tell you about a couple of things that, if considered while reviewing and editing your code, will also fix your problem.
The documentation for String.charAt http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#charAt(int) throws an error when you attempt to access out-of-bounds items in the String. Make sure that you check that you're not attempting to look beyond the length of the String before you go calling charAt all willy-nilly! If you're currently "considering" the 'T' in "INPUT" and you go trying to look at the next two characters, Java will complain.
Second, and this is more of a general thing (though it does need to be fixed in your code above); the '++' operator doesn't do what you appear to think it actually does. When you do this: in.charAt(ind++)=='H', you may think you're just checking on the value at the next index, but you're actually advancing the index at the same time! The '++' operator is very handy, but it has a side affect that trips up a lot of beginners: it assigns itself + 1 to itself! That means that if you're on the 'I' in "INPUT" and somewhere within your loop you call ind++ once, you'll be on 'P' at the next iteration of your loop! When you see '++' remember that you're changing the value of the variable.
Good luck!

Are 0.0 and 1.0 considered magic numbers?

I know that -1, 0, 1, and 2 are exceptions to the magic number rule. However I was wondering if the same is true for when they are floats. Do I have to initialize a final variable for them or can I just use them directly in my program.
I am using it as a percentage in a class. If the input is less than 0.0 or greater than 1.0 then I want it set the percentage automatically to zero. So if (0.0 <= input && input <= 1.0).
Thank you
Those numbers aren't really exceptions to the magic number rule. The common sense rule (as far as there is "one" rule), when it isn't simplified to the level of dogma, is basically, "Don't use numbers in a context that doesn't make their meaning obvious." It just so happens that these four numbers are very commonly used in obvious contexts. That doesn't mean they're the only numbers where this applies, e.g. if I have:
long kilometersToMeters(int km) { return km * 1000L; }
there is really no point in naming the number: it's obvious from the tiny context that it's a conversion factor. On the other hand, if I do this in some low-level code:
sendCommandToDevice(1);
it's still wrong, because that should be a constant kResetCommand = 1 or something like it.
So whether 0.0 and 1.0 should be replaced by a constant completely depends on the context.
It really depends on the context. The whole point of avoiding magic numbers is to maintain the readability of your code. Use your best judgement, or provide us with some context so that we may use ours.
Magic numbers are [u]nique values with unexplained meaning or multiple occurrences which could (preferably) be replaced with named constants.
http://en.wikipedia.org/wiki/Magic_number_(programming)
Edit: When to document code with variables names vs. when to just use a number is a hotly debated topic. My opinion is that of the author of the Wiki article linked above: if the meaning is not immediately obvious and it occurs multiple times in your code, use a named constant. If it only occurs once, just comment the code.
If you are interested in other people's (strongly biased) opinions, read
What is self-documenting code and can it replace well documented code?
Usually, every rule has exceptions (and this one too). It is a matter of style to use some mnemonic names for these constants.
For example:
int Rows = 2;
int Cols = 2;
Is a pretty valid example where usage of raw values will be misleading.
The meaning of the magic number should be obvious from the context. If it is not - give the thing a name.
Attaching a name for something creates an identity. Given the definitions
const double Moe = 2.0;
const double Joe = 2.0;
...
double Larry = Moe;
double Harry = Moe;
double Garry = Joe;
the use of symbols for Moe and Joe suggests that the default value of Larry and Harry are related to each other in a way that the default value of Garry is not. The decision of whether or not to define a name for a particular constant shouldn't depend upon the value of that constant, but rather whether it will non-coincidentally appear multiple places in the code. If one is communicating with a remote device which requires that a particular byte value be sent to it to trigger a reset, I would consider:
void ResetDevice()
{
// The 0xF9 command is described in the REMOTE_RESET section of the
// Frobnitz 9000 manual
transmitByte(0xF9);
}
... elsewhere
myDevice.ResetDevice();
...
otherDevice.ResetDevice();
to be in many cases superior to
// The 0xF9 command is described in the REMOTE_RESET section of the
// Frobnitz 9000 manual
const int FrobnitzResetCode = 0xF9;
... elsewhere
myDevice.transmitByte(FrobnitzResetCode );
...
otherDevice.transmitByte(FrobnitzResetCode );
The value 0xF9 has no real meaning outside the context of resetting the Frobnitz 9000 device. Unless there is some reason why outside code should prefer to send the necessary value itself rather than calling a ResetDevice method, the constant should have no value to any code outside the method. While one could perhaps use
void ResetDevice()
{
// The 0xF9 command is described in the REMOTE_RESET section of the
// Frobnitz 9000 manual
int FrobnitzResetCode = 0xF9;
transmitByte(FrobnitzResetCode);
}
there's really not much point to defining a name for something which is in such a narrow context.
The only thing "special" about values like 0 and 1 is that used significantly more often than other constants like e.g. 23 in cases where they have no domain-specific identity outside the context where they are used. If one is using a function which requires that the first parameter indicates the number of additional parameters (somewhat common in C) it's better to say:
output_multiple_strings(4, "Bob", Joe, Larry, "Fred"); // There are 4 arguments
...
output_multiple_strings(4, "George", Fred, "James", Lucy); // There are 4 arguments
than
#define NUMBER_OF_STRINGS 4 // There are 4 arguments
output_multiple_strings(NUMBER_OF_STRINGS, "Bob", Joe, Larry, "Fred");
...
output_multiple_strings(NUMBER_OF_STRINGS, "George", Fred, "James", Lucy);
The latter statement implies a stronger connection between the value passed to the first method and the value passed to the second, than exists between the value passed to the first method and anything else in that method call. Among other things, if one of the calls needs to be changed to pass 5 arguments, it would be unclear in the second code sample what should be changed to allow that. By contrast, in the former sample, the constant "4" should be changed to "5".

Categories

Resources