Android/Java converting from int to String without allocations? - java

got thinking about having to repeatedly convert from int to String over the course of one of the apps I'm creating for Android. I sat down and wrote a little utility class that I think would alleviate the allocation of lurking variables that you cannot see because of function calls like Integer.toString(), and etc...
private int[] iMods = {
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000};
private int tmpInt = 0;
private int MAX_DIGITS = 6;
private char[] cScoreDigit = new char[MAX_DIGITS];
private int[] iScoreDigit = new int[MAX_DIGITS];
private StringBuilder mScoreStringBuilder = new StringBuilder("000000");
public String intToString(final int pInt, final int pMAX_DIGITS){
MAX_DIGITS = pMAX_DIGITS;
for (tmpInt = 1; tmpInt <= MAX_DIGITS; tmpInt++){ // Set each cScoreDigit to proper equivalent of iScoreDigit without cast!
switch ((pInt % iMods[tmpInt]) / iMods[tmpInt - 1]){
case 0:
cScoreDigit[MAX_DIGITS - tmpInt] = '0';
break;
case 1:
cScoreDigit[MAX_DIGITS - tmpInt] = '1';
break;
case 2:
cScoreDigit[MAX_DIGITS - tmpInt] = '2';
break;
case 3:
cScoreDigit[MAX_DIGITS - tmpInt] = '3';
break;
case 4:
cScoreDigit[MAX_DIGITS - tmpInt] = '4';
break;
case 5:
cScoreDigit[MAX_DIGITS - tmpInt] = '5';
break;
case 6:
cScoreDigit[MAX_DIGITS - tmpInt] = '6';
break;
case 7:
cScoreDigit[MAX_DIGITS - tmpInt] = '7';
break;
case 8:
cScoreDigit[MAX_DIGITS - tmpInt] = '8';
break;
case 9:
cScoreDigit[MAX_DIGITS - tmpInt] = '9';
}
}
// Delete all 0's
mScoreStringBuilder.delete(0, mScoreStringBuilder.length());
return mScoreStringBuilder.append(cScoreDigit).toString();
}
Now I'm just curious as to A) whether this is actually the correct way to do something like this, and B) whether something like this is worth looking into because of the extra math taking place on each step? Seems counter productive, but would at least restrain the GC from running correct? Thanks in advance!
[EDIT]
It's been brought to my attention that the StringBuilder.toString() will actually allocate a temporary object, which is what I was trying to avoid. Any other way to simply convert from char[] to String without having an allocation? Or like stated below is this just not possible with String class?

No, the toString at the end creates a new String (Check the code if you like, java library sources are all available).
Since strings are immutable, there is really no way to avoid allocation because you return a string.
If you return the string builder you used to build your number in and reused it the next time you were called and NEVER converted it to a string you'd be fine, but the second you convert it to a string (no matter how you did it) you are allocating memory.
To do this your method would either have to accept a passed-in mutable object (StringBuilder or char array) or it would have to reuse a static one (making it single threaded)
I tried this once and it always comes down to converting it to a string at some point undoing all your work and making it even slower than it would have been if you'd just used the obvious way.
Also remember that in Java short-term memory allocations aren't as bad as you'd think--they are more like stack allocations in C in terms of performance.
The research and testing I did indicated that the one thing you can do is avoid concatenating strings in a loop--everything else (including one-time string concatenations) the simplest code will be just as fast or faster than anything you can come up with.

Related

Switch Statement in Java netbeans

I have different fields using the same parameters i.e. same grading scale. I want to use switch statement to return grades for different fields using the same scale. Something like this. I thought that there was something like this: switch (attend, job, initiative) { that would combine the three variables.
int attend = 5;
int job = 5;
int initiative = 5;
switch (attend) {
case 1:
getattendo = 5;
break;
case 2:
getattendo = 4;
break;
case 3:
getattendo = 3;
break;
case 4:
getattendo = 2;
case 5:
getattendo = 1;
break;
default:
getattendo = 0; // null
}
Your help is appreciated.
fmk
Enum works well with switch cases. So, you can define an enum that represents your range of value of it is a finite and reasonable range of values :
public enum OPTIONS {
OPTION1(5, 5, 5),
OPTION2(5, 2, 4),
OPTION3(1, 2, 3),
OPTION4(4, 4, 1);
private final int attend;
private final int jobs;
private final int initiative;
Directive(int attend, int jobs, int initiative) {
this.attend = attend;
this.jobs = jobs;
this.initiative = initiative;
}
// ... optional setters & getters
}
Given your create OPTION Enum, you can use a switch to handle the different cases :
switch (OPTION) {
case OPTION1:
getattendo = 5;
break;
case OPTION2:
getattendo = 4;
break;
case OPTION3:
getattendo = 3;
break;
case OPTION4:
getattendo = 2;
break;
default:
getattendo = 0; // null
break;
}
Note: Your switch is legitimate only if you have a finite number of condition. Otherwise, use a method to calculate your result.
A trick you use utilizes the unary or operation for checking binary digit presence.
This will help get you started on switching according to various conditions.
This is similar to how file permissions work in Linux.
public class ScoreCombinator {
public static final int ATTEND = 1; // binary: 001
public static final int JOB = 2; // binary: 010
public static final int INITIATIVE = 4; // binary: 100
public static void main(String[] args) {
evaluate(ATTEND | INITIATIVE); // Attend and Initiative
evaluate(INITIATIVE | ATTEND | JOB); // Attend, Job, and Initiative
}
private static void evaluate(int value) {
switch (value) {
case ATTEND: {
System.out.println("Attend");
break;
}
case ATTEND | JOB: {
System.out.println("Attend and Job");
break;
}
case ATTEND | JOB | INITIATIVE: {
System.out.println("Attend, Job, and Initiative");
break;
}
case ATTEND | INITIATIVE: {
System.out.println("Attend and Initiative");
break;
}
case JOB: {
System.out.println("Job");
break;
}
case JOB | INITIATIVE: {
System.out.println("Job and Initiative");
break;
}
case INITIATIVE: {
System.out.println("Initiative");
break;
}
}
}
}
Something like switch(a,b,c) is not possible.
If all values are the same, just use one of the valueslandmaybe verify that all values are the same).
However, there are workarounds if you want to switch-case with multiple numbers:
mathematical solution
For example, you could use prime numbers for this. As you only want to switch numbers, this is possible as long as there is a prime number higher than the highest expected value(for attend, prime and job).
Instead of switch(attend, job, initiative), you use switch((attend*prime+job)*prime+initiative) and instead of case (exampleAttend, exampleJob, exampleInitiative):, you use case ((exampleAttend*prime+exampleJob)*prime+exampleInitiative):
Note that prime must be the same in the switch and case statements.
Note that you should test if any of the input numbers is higher than the prime. This would logically lead to the default case but it could lead to collissions.
You may also want to make sure that the prime to the forth power is lower than the max value of the data type or there may be overflows.
On the other side, this method should be more performant than the second.
simple string concadation
Another option is to work with strings. As the string representation of a number is unique (to the number) and it does not contain some characters (like spaces), you can concadate those numbers and use such a character to seperate them.
Instead of switch(attend, job, initiative), you use switch(attend+" "+job+" "+initiative) and instead of case (exampleAttend,exampleJob,exampleInitiative):, you use case (exampleAttend+" "+exampleJob+" "+exampleInitiative):.
This is obviously easier and fail-safer than the first method involving prime numbers but there should be a performance impact as concadating strings is slower than multiplying ints.
Another possibility is to use enums. Look at the other answer by #Hassam Abdelillah
if you want to know how this works. If you like the enum approach, feel free to upvote the other answer.

comparing the value of each round of a for loop?

Is there a way to grab the resulting number from each iteration of this loop and compare it to the next?
This is a Slot Machine Sim in Java,
I'm trying to find a way to see how many of the results match.
so I thought I would capture the number that is resulted from each round of the For loop and compare it to the previous one.
but I have no idea how to write that?
is there a better way to do this?
what I have so far:
for (int count=1; count<= 3 ; ++count)
{
number = slotM.nextInt(6);
switch (number)
{
case 0:
System.out.print("-cherries-");
break;
case 1:
System.out.print("-Oranges-");
break;
case 2:
System.out.print("-Palms-");
break;
case 3:
System.out.print("-Bells-");
break;
case 4:
System.out.print("-Melones-");
break;
default:
System.out.print("-Bars-");
break;
}
System.out.print(number);
}
Yep there are several better ways. If you have a fixed number of options (6 in your case) an enum might be a good option:
enum Picture {
CHERRIES, ORANGES, PALMS, BELLS, MELONS, BARS;
public String getName() {
return "-" + name().substring(0, 1) + name().substring(1).toLowerCase() + "-";
}
That way you can store your numbers as pictures rather than numbers.
Picture pictures[3];
Random random = new Random();
for (int i = 0; i < pictures.length; i++)
picture[i] = Picture.values[random.nextInt(pictures.length)];
To get the printed version:
for (Picture picture: picture)
System.out.print(picture.getName());
You’ll need some kind of storage outside of the loop so that each iteration can reference it.
int[] results Look in to arrays - you can put the results of each round into a part of the array, and look up the value.
You are declaring your count variable in the for loop, just declare outside and make a comparison with it

Coming from C, I need some help figuring out, how to best generate Chess-Bitmaps from an input-string

I'm attempting to generate some Bitmaps from an input-string for the chess-variant "Anti-King Chess". Unfortunately I have to do it in Java, which I'm not super familiar with. In the few lines of code i wrote so far I already found that a few things are thought about very differently in Java than in C and it's derivatives.
Like you see in the except below, I have a constructor, that takes the board as string. I iterate over it and call the function placePiece with the corresponding bitmap-long, so that that might get updated correctly.
Now I come to my first question:
Since you can't make a "call-by-reference" in Java I decided to return the updated long. That feels pretty "hacky". What would be a better way of updating the bitmaps without writing a function for every type of piece?
Second Question:
What does Java do, when I assign the return value of a function to a variable? Is it as run-time efficient as just changing a global variable, like I do with "pieces", "whitePieces" and "blackPieces"?
/*
* Parse the starting board state and build the corresponding bitmaps
*/
public Board(String[] board) {
//Go through all lines
for(int i = 0; i < board.length; i++) {
//Go through all positions
for(int j = 0; j < board[i].length(); j++) {
switch(board[i].charAt(j)) {
//Pawns
case 'P': pawns = placePiece(pawns, i, j, true); break;
case 'p': pawns = placePiece(pawns, i, j, false); break;
//Bishop
case 'B': bishops = placePiece(bishops, i, j, true); break;
case 'b': bishops = placePiece(bishops, i, j, false); break;
//Rook
case 'R': rooks = placePiece(rooks, i, j, true); break;
case 'r': rooks = placePiece(rooks, i, j, false); break;
//Knight
case 'N': knights = placePiece(knights, i, j, true); break;
case 'n': knights = placePiece(knights, i, j, false); break;
//Queen
case 'Q': queens = placePiece(queens, i, j, true); break;
case 'q': queens = placePiece(queens, i, j, false); break;
//King
case 'K': kings = placePiece(kings, i, j, true); break;
case 'k': kings = placePiece(kings, i, j, false); break;
//Anti-King
case 'A': antikings = placePiece(antikings, i, j, true); break;
case 'a': antikings = placePiece(antikings, i, j, true); break;
}
}
}
}
/*
* Function to place a Piece at the appropriate place in the bitmaps
*/
private long placePiece(long map, int row, int column, boolean white) {
//Place a 1 in the right position of the pieces long
pieces |= 1L << (row*COLUMN_NUM + column);
//Place a 1 at the right position in either the black or white pieces
if(white == true) {
whitePieces |= 1L << (row*COLUMN_NUM + column);
}else {
blackPieces |= 1L << (row*COLUMN_NUM + column);
}
//Place a 1 at the right position in the pawn long and return the changed set
return map | 1L << (row*COLUMN_NUM + column);
}
Edit: Changed (long)1 to 1L as suggested by RaceYouAnytime.
In java all primitive types are immutable, so there is no way of updating a long.
What you did is right.
You are asking questions about performance that are much above the pay grade of the typical developer.
To have true answers to your question one should look at the bytecode generated after compilation.
For example you can ask yourself if your placePiece function would be inlined or not (which possibly has a much higher impact then updating a global varible or not).
Java programmers are not really much obsessed by performance, not when dealing with in-memory operation, since we mostly deal with IO (DB, HTTP, Files) which are order of magnitude slower then memory.
So, in general we try to optimize IO, but we care much less about in memory ops.
I think you can scrape some microseconds by checking if your methods gets inlined, if not so you may use static final methods, which are essentially faster.
Methods in java are all virtual apart from final methods which cannot be overridden.
Use primitive when you can (but often the compiler would do that for you).
That being said, concerning coding style ... you almost never use final method, an try not to use primitives, which goes against my performance tips, but fits into the java mentality of abstracting as much as you can even at the expense of performance (up to a point).
All primitive types have wrapper classes in Java that can be used to avoid the problem you're talking about
Should I just pass a one-element Array with it then?
Just use Long. (the wrapper class)
private void placePiece(Long map, int row, int column, boolean white) {
documentation can be found here: https://docs.oracle.com/javase/7/docs/api/java/lang/Long.html
Note that instantiating a Long value is more efficient if you use the "valueOf()" method.
https://docs.oracle.com/javase/7/docs/api/java/lang/Long.html#valueOf(long)
Long pawns = Long.valueOf(14L);
...
placePiece(pawns, i, j, true); break;
Also, since you're concerned about efficiency, you may want to stick with primitive types. In that case, though, it would be more efficient to type 1L rather than (long)1 so that you aren't recasting one primitive type to another every time you instantiate.
I found a great solution for my problem here:
https://chessprogramming.wikispaces.com/Bitboard+Board-Definition
Basically, you define an array, that contains all the bitmaps, then you define constants, in the given example an Enum, which doesn't work in Java, but there are ways to define constants. Then you just have to pass the constant and can have the array, that contains all the bitmaps globally.
You then call it by invoking something like board[PAWN].

Most concise way to express this Java conditional without checking a value twice

I have a variable, x.
I want to call a method m() only if x is one of two possible values.
When calling m(), I want to pass an argument to it, whose value depends on the value of x.
Is there a way to do this in Java without checking the value of x more than once, and calling/writing m() in one place only (i.e. not in multiple branches of an if statement)?
One solution I'm entertaining:
switch (x) {
case 1:
y = "foo";
break;
case 2:
y = "bar";
break;
default:
y = null;
break;
}
if (y != null) m(y);
But I can't help but feel this is technically checking x twice, just obscuring this fact by adding a "proxy" for the second check.
(To clarify why the constraints are what they are: when reading code, I have a hard time understanding logic that branches a lot when there is a high degree of duplication between branches - it becomes a game of "spot the difference" rather than simply being able to see what is happening. I prefer to aggressively refactor such duplication away, which is a habit that serves me well in Ruby, JS, and other languages; I'm hoping I can learn to do the same for Java and make code easier for me and others to understand at a glance.)
I'm not sure of what you want to do, but you can maybe use a Map to get the 'y' parameter from 'x'
Map<Integer, String> map = new HashMap<>();
map.put(1, "foo");
map.put(2, "bar");
if (map.containsKey(x)) {
m(map.get(x));
}
Use "goto" or equivalent:
void do_m_if_appropriate() {
// x and y are assumed to be eg. member variables
switch (x) {
case 1:
y = "foo";
break;
case 2:
y = "bar";
break;
default:
return; // this is the "goto equivalent" part
}
m(y);
}
Above is pretty elegant. If necessary, it's also trivial to change it to return true or false depending on if it called m(), or just y or null.
You can also do tricks with loop constructs, though some might say this is abuse of the loop construct, and you should comment it accordingly:
do { // note: not a real loop, used to skip call to m()
switch (x) {
case 1:
y = "foo";
break;
case 2:
y = "bar";
break;
default:
continue; // "goto equivalent" part
}
m(y);
} while(false);
Here's a solution with Optionals (my Java syntax might be slightly incorrect). Note that to you, the code looks like so, but implementation wise, it's similar to the example you posted (i.e. checks whether y is an exceptional value).
switch (x) {
case 1:
y = Optional<String>.of("foo");
break;
case 2:
y = Optional<String>.of("bar");
break;
default:
y = Optional<String>.empty();
break;
}
y.map((m's class)::m);
result = y.orElse( <value result should take if x was invalid> );
Actually it may be better to modify m() to return an Optional and just return empty if y is not valid, but I assume you want to do this check caller-side.
Why not
switch (x) {
case 1:
y = "foo";
m(y);
break;
case 2:
y = "bar";
m(y);
break;
}

How are "ranges" defined in Java?

I have a chunk of code that needs to determine if a given integer is between a set of other integers. I'd also like to have this in a case statement so as to not have a surplus of if..else statements everywhere. Here's a bit of the code:
switch (copies) {
case copies >= 0 && copies <= 99: copyPrice = 0.30; break;
case copies >= 100 && copies <= 499: copyPrice = 0.28; break;
case copies >= 500 && copies <= 749: copyPrice = 0.27; break;
case copies >= 750 && copies <= 1000: copyPrice = 0.26; break;
case copies > 1000: copies = 0.25; break;
}
where copies is an integer and copyPrice is a double. I get several errors saying that it expects to receive a integer but gets a boolean instead. What is the best (or optimal) way of setting this up? Any help is greatly appreciated!
This line (and similar):
case copies >= 0 && copies <= 99:
Returns a compiler error since it gives a boolean but the compiler expects an int since copy is declared as int.
One way to solve this is using an array with the desired ranks, and have a switch statement for the index found:
public double calculateCopyPrice(int copies) {
int[] range = { 99, 499, 749, 1000 };
double copyPrice = 0;
int index = -1;
for (int i = 0; i < range.length; i++) {
if (range[i] >= copies) {
index = i;
break;
}
}
switch (index) {
case 0: copyPrice = 0.30; break;
case 1: copyPrice = 0.28; break;
case 2: copyPrice = 0.27; break;
case 3: copyPrice = 0.26; break;
default: copyPrice = 0.25; break;
}
//probably more logic here...
return copyPrice;
}
After some tests, I've found a more flexible solution using a TreeMap<Integer, Double> which allows you to have a specie of range (what you're looking for) and ease the search by using TreeMap#ceilingEntry:
//TreeMap to store the "ranges"
TreeMap<Integer, Double> theMap = new TreeMap<Integer, Double>();
//add the data
theMap.put(99, 0.3);
theMap.put(499, 0.28);
theMap.put(749, 0.27);
theMap.put(1000, 0.26);
//the "default" value for max entries
theMap.put(Integer.MAX_VALUE, 0.25);
//testing the solution
Double ex1 = theMap.ceilingEntry(50).getValue();
Double ex2 = theMap.ceilingEntry(500).getValue();
Double ex3 = theMap.ceilingEntry(5000).getValue();
Double ex4 = theMap.ceilingEntry(100).getValue();
System.out.println(ex1);
System.out.println(ex2);
System.out.println(ex3);
System.out.println(ex4);
java has no native concept of "ranges", let alone support for them in case statements.
usually, when faced with this kind of logic i personally would do one of 2 things:
just have a chain of if-else statements. doesnt even habe to be a chain:
public static double calculateCopyPrice(int copies) {
if (copies > 1000) return 0.25;
if (copies >= 750) return 0.26;
//etc
}
this code has no "else" branches and is just as much typing as the switch syntax you'd like. possibly even less (i only check a single bound every time)
you could use an enum, say:
public enum Division {UNDER_100, 100_to_500, ... }
and then :
Division division = categorize(copies);
switch (division) {
case UNDER_100:
//etc
}
but this is serious overkill for what youre trying to do. i'd use that if this division is also useful elsewhere in your code.
Switch case function must have an exact number in case. For example:
case 0:
case 1:
You're trying to use case from some value to some value and it's not implemented that way in Java. For your problem, you must use if-else statement since it's impossible to do it with switch case. Hope it helped.
Look the problem is very basic..
In a switch statement it allows only the following datatypes and wrapper classes
Byte,short,char,int,Byte,Short,Character,Integer,enum,String..
If you are passing anything other than that will give you an error.
In your case the condition which you are evaluating will give you result which is a Boolean value.
NavigableMap.seilingEntry() may be a good solution in many cases,
but in other cases the following may be clearer:
double getPrice(int copies){
return copies>1000 ? 0.25
: copies>750 ? 0.26
: copies>500 ? 0.27
: copies>100 ? 0.28
: copies>0 ? 0.30
: 0; // or check this condition first, throwing an exception
}

Categories