Why does IntelliJ wants me to change this? - java

A simple line of code:
String thing = "Something";
thing += " something else" + " and more.";
IntelliJ IDEA offers to change this line into 4 other ways to accomplish the same result:
String.format()
StringBuilder.append()
java.text.MessageFormat.format()
Replace += with =
Why? What is so wrong with +=? Can anyone explain this please? Thanks.

In general case, the result is not the same. + operator allocates intermediate string, which requires additional memory.
String thing = "Something";
thing += " something else" + " and more."; // two allocations: to compute string inside expression ```" something else" + " and more."```` and to execute ```+=```
By using StringBuilder you don't allocate intermediate result, e.g. less memory is needed.
In your case with short lines and without loops no actual performance boost is expected. However with loops you receive O(N^2) complexity. Please check this answer with explained example.

I am assuming you are referring to this:
This is not actually a fix "problem" with your code, as indicated by the pencil icon. Fixes to problems with your code are identified with a lightbulb, such as not using the value of thing:
The pencil just means "here's a shortcut to change your code, so you don't have to change it manually". Changing a a += b to a = a + b usually isn't that much work, but other things, like changing a for-each loop to a regular for loop, is.
This could be useful if you suddenly remembered that you need the index of the array for something.

Related

java spacing when writing to a file

just a beginner in java doing a simple reading file processing some data and writing to a file, however whenever I print to a file I get this inconsistent spacing such as shown below. Especially the zeros are throwing me off. Right now I am padding the strings with empty spaces but I am sure there are better suggestions out there to have consistent spacing between strings in a file. Thanks for the help. I have attached a picture of the inconsistent printing, especially the zeros.
In Apache Commons StringUtils library there are convenient methods to set the proper pad - e.g. rightPad seems to be useful in your case - you could make something like
String row = StringUtils.rightPad(firstValue, lengthOfTheLongestValueInColumn1 + definedColumnMargin) + StringUtils.rightPad(secondValue, lengthOfTheLongestValueInColumn2 + definedColumnMargin) // + ... etc
If these lengthOfTheLongestValueInColumn variables would be calculated dynamically then it would work perfectly but you could also just hardcode some reasonable value (if you know that no value will be longer than, let say, 20 it could have value of 20)
I think best option will be to use String format
return String.format("%1$" + length + "s", inputString)
where length is max size of your digit
you can read more here

HashMap- java program issues

Rather than explaining some big problem, I'll skip all that and list the small loop I am struggling with. Anyways, I have to print the key of a map, so I am using a special way to print the key by switching the value and the key around.
for (int i = 0; i < elementData.length; i++){
System.out.print("[" + i + "]");
for (Entry<HashEntry<E>, Integer> entry : foob.entrySet()){
if (entry.getValue().equals(i)){
System.out.print(entry.getKey().toString());
}
}
}
This is my goal: Print [0][1][2][3] like that all the way to 20. Along with that, 9 numbers will go in between those numbers in parens randomly, based on my program.
Here is my result:
[0][1]HashSet$HashEntry#7d4991ad[2][3][4]HashSet$HashEntry#4554617cHashSet$HashEntry#28d93b30[5][6][7][8][9]HashSet$HashEntry#232204a1[10][11]
So there's just some trick to make it not print all this machine language looking stuff. Anyways, what do I have to do? Looks like 1 thing was supposed to come after [1], 2 things after [4], something after [9], and so on.
Thanks!
So there's just some trick to make it not print all this machine language looking stuff?
Yea.
Don't try to print an instance of a class that doesn't override Object.toString(). That "machine language looking stuff" is simply the output of Object.toString().
However, I suspect that your real code is doing this:
if (entry.getValue().equals(i)){
System.out.print(entry.toString());
}
because "HashSet$HashEntry#7d4991ad" looks like the output you would get if you printed a HashSet.HashEntry object. (The other possibility is that you have used HashSet.HashEntry objects as keys in your Map.)

Is there a java tool that allows code fragments to be tested?

I'm using Blue J and would love to be able to test out small fragments of code without having to create a new program, create a class, and write a method. Does Blue J have any way to run simple segments of code (like trying out a new method) without creating a whole new program?? Similar to operating in the Python shell rather than a new file.
The code pad allows you to run some code and instantiate objects. It is helpful for testing small bits of code, but not the type of tool that allows for complete methods as far as I understand. The code pad can be accessed under View -> Show code pad.
Sorry, I'm not able to comment on answers yet - you can write as much code in the code pad as you want, really, probably including full methods if you really wanted to - the only differences between the code pad and regular coding are 1. You don't need to write any 'boilerplate', ie code does not have to be in a method or class structure, and 2., BlueJ will evaluate each line as you enter it, rather than all at once.
Don't forget that SHIFT + ENTER goes to the next line without 'sending' what you've typed to the compiler, too - though in most cases you can write line-by-line, this can help you practice formatting and keep multiple statements (with semicolons of course) from getting unreadable and confusing to debug.
Just as a proof-of-concept, try the below out in the BlueJ codepad. It should work either as one block (using shift+enter) OR as a series of individual lines:
int apples = 5;
int pears = 4;
int fruit = apples + pears;
System.out.println("we have " + apples + " apples and " + pears + " pears.");
System.out.println("that's " + fruit + " pieces of fruit");
It seems, however, that while coming up with examples I've found a limitation. While if (apples > pears) System.out.println("We have more apples than pears"); works fine, it doesn't seem to like me adding an else statement. But if/else statements are probably reaching the threshold where you are better off writing your code out properly, anyway. The code pad is more useful for "how does this work" type of queries that beginners like us tend to have, or to test an individual line before putting it into your method. I often use it to experiment with formatting/structure problems like "is it possible to do evaluations within a println statement" (It is - in the above example we could have just had System.out.println("that's " + (apples + pears) + " pieces of fruit");

Primitive + "" versus Wrapper.toString(primitive)

When needing to convert a primitive to a String, for example to pass to a method that expects a String, there are basically two options.
Using int as an example, given:
int i;
We can do one of:
someStringMethod(Integer.toString(i));
someStringMethod(i + "");
The first one is the "formal" approach, and the second one seems somewhat of a "hack".
It's certainly a lot less code and easier to read the "hack" IMHO.
But is it "good" coding style to use the "hack"?
The best way to convert * to String is to use:
String.valueOf(x)
it works with primitive types, wrapper classes and Object who do implement toString().
where x is any kind of primitive or object. If it is null it returns the string 'null'.
The reason why this is best, is because using "+" operand implies String concatenation, plus the "" implies String instantiation. If you decompile a class using ""+something you'll see the compiler translate that to multiple operations.
"" concatenation result is the same as String.valueOf() but it is a little bit more expensive.
The performance difference is probably negligible, but good programmers don't write '"" + something' to convert something to a String when there is a better way, which happens to be the correct way :).
For arrays, have a look at Arrays.toString() and -better- Arrays.deepToString()
But is it "good" coding style to use the "hack"?
Sometimes syntactic hack make the code better. But the case above, is not really one of those cases.
"" concatenation not considered good code.
An example of a useful syntactic hack is the double brace instantiation:
List<String> list = new ArrayList<String>() {{
add("foo");
add("bar");
add("baz");
}};
instead of
List<String> list = new ArrayList<String>();
list.add("foo");
list.add("bar");
list.add("baz");
The ""+something is more a code smell than a hack that improve readability; anybody with some experience would think to a Java developer who lack some knowledge of the API and the language.
Other interesting "hacks" are fluent APIs (like Mockito), dsl, or things like lambda4j, which is quite an hack.
It's not a good idea, but it's not going to be very harmful.
In both examples Integer.toString() is being called by the JVM (even if not directly in the first case).
In the second example, the JVM possibly constructs two strings and then produces the result of the concatenation. Depending on optimizations this may result in 0, 1 or 2 extra strings to garbage collect.
From a code writing perspective, the third is shorter, but also possibly less transparent as to what is happening.
The problems with the second approach in readability follow:
int i = 1, j = 2;
someStringMethod(i + j + "" + i + j + "");
Produces:
someStringMethod(312);
and not
someStringMethod(33);
When strings are formed using + sign, jvm will create a intermediate string/stringbuffer object to carry out trasnformation, which is not the optimum way.
Also, + sign is left associative,so when used in expressions like ""+1+2 will result in 12 and not "3".So it's better to use String.toValue() or Type.toString().
Concatenation symbol in java is +.
So you convert the result of (i + "") to String because you concat an empty string to a number in your example code.
The two ways are good but I normally use String.valueOf(x);

Recursion - What does it do

I'm at my wit's end... I understand the easier examples of recursion, but I when it gets tricky I don't have a clue. Here is an example. I would be glad if someone can say what it does. What does the compiler do...
public static char mystery(String s, int n, int m)
{
if (n==1) return s.charAt(m);
char first = mystery(s, n/2, m*2);
char second = mystery(s, n/2, m*2 +1);
System.out.print(first + " " + second + " ");
return first;
}
What is printed when the method is called with:
mystery("fredpass", 5, 1)
The answer is p a s s p s
I don't have a CLUE how they get there...
Would REALLY appreciate it if someone can help me with this matter. On other places on the internet they only explain factorial - easy examples. Not sure what happen if you call it twice as in char first = mystery ( blah ); and then again char second = mystery ( blah );
Just trace the calls by hand:
mystery(5, 1)
first = mystery(2, 2)
first = mystery(1, 4) = 'p'
second = mystery(1, 5) = 'a'
second = mystery(2, 3)
...
and so on. Give yourself enough paper to draw a complete picture of the call stack, the state of a function call, and the local variables. For example, after the innermost call in my picture prints "p a ", it returns 'p', so I would write that letter after mystery(2, 2).
So, you already know examples of recursion and how it can be used.
Perhaps what you are missing is why recursion works. In order to understand this you need to know what happens when a method is called. Familiarize yourself with the call stack.
In terms of what happens logically, you should just consider 'walking' across the code sequentially. When you call a method recursively, it will simply return the result and continue execution as it would in any other procedural code. Every method call however has its own scope of variables which are only valid in that particular call of the recursion.
Hand "executing" as described in #jleedev's answer is a useful exercise, especially if you've never done it before.
An alternative is to run the code under the control of a Java debugger, and single step the execution while examining the call stack / local variables. This is less error prone, though if you do it too quickly you might miss important details of what is actually going on.
Don't be too worried that it is a mystery to you what the mystery function actually does. It is clearly designed to be difficult to understand. (And I cannot see any point to it ... apart from being mysterious.) Most recursive functions that you are likely to encounter will do something useful, and will be easier to understand ... with experience ...
For every recursion there are two things to be considered
Every recursive method should have a base case.
Every recursion should progress towards this base case

Categories

Resources