I am working with an Android app, and I want to print out a HashMap's keys and values in a certain manner. Let's say the following are the contents of the HashMap:
11: 000010
12: 102643
24: 877
3: 990000
h: 6008770000
m: 0800
I want to print out the HashMap keys and values in such a way that the keys with letters should be printed first alphabetically, followed by the numeric keys in ascending order:
h: 6008770000
m: 0800
3: 990000
11: 000010
12: 102643
24: 877
What I am doing right now is:
Get the key set and save it to an ArrayList
Sort the ArrayList using a comparator
Print out the values in the map by using the sorted list
Here's my code:
List<String> keyList = new ArrayList<>(requestMap.keySet());
Collections.sort((keyList), comparator);
for(String key : keyList) {
Log.d(key, requestMap.get(key));
}
Comparator<String> comparator = (o1, o2) -> {
if (o1 == null) return -1;
else if (o2 == null) return 1;
if(TextUtils.isDigitsOnly(o1) && TextUtils.isDigitsOnly(o2)) {
return Integer.compare(Integer.parseInt(o1), Integer.parseInt(o2));
}
if(!TextUtils.isDigitsOnly(o1)) {
return -1;
} else {
return o1.compareTo(o2);
}
};
It's so far working, but for some cases I don't get the desired order. For example, for a specific Map I always get the following result:
3: 005000
4: 000000058985
12: 095508
22: 022
h: 6008770000
m: 0221
11: 000004
13: 0120
24: 877
25: 00
35: 77690088000000131D20077100000F
37: QWERTY123456
41: 00000003
42: 100000004000000
48: 456789123451 0000050201
60: 000001
61: 0201020000000045000000000300000000000015000102000000049770000000049770000000001659
I made the comparator with the idea that the alphabetical strings should be sorted first, followed by the numeric strings, but right now I'm having doubts if my logic for the comparator is correct. Can anyone point me in the right direction?
if(TextUtils.isDigitsOnly(o1) && TextUtils.isDigitsOnly(o2)) {
return Integer.compare(Integer.parseInt(o1), Integer.parseInt(o2));
}
So the case where both are digits only is dealt with.
if(!TextUtils.isDigitsOnly(o1)) {
return -1;
This is the case where the first has non-digits. This is return -1 even if the second has non-digits. When both have non-digits we should be comparing.
} else {
return o1.compareTo(o2);
This is the case where the first is digits, so don't want to compare. Because we have excluded both are digits only, the second must be non-digits (though we shouldn't be comparing).
}
So, it looks like you certainly want to remove the !!
You should probably also cover all cases. Either have a condition whether you should cover the compare case
!TextUtils.isDigitsOnly(o1) && !TextUtils.isDigitsOnly(o2)
or nest
if (TextUtils.isDigitsOnly(o1)) {
if (TextUtils.isDigitsOnly(o2)) {
...
} else {
...
}
} else {
if (TextUtils.isDigitsOnly(o2)) {
...
} else {
...
}
}
Related
Can someone explain to me, how my method here in java that expects a int, but accepts '!' as an argument? further more, how can it interpet it as 33 when i debug it, but when i do System.out.println(Character.getNumericValue('!')); it prints -1?
here is the code guys:
public abstract class Stuff {
public static char getCharacterFromNumber(int number) throws InvalidCharException {
if(number>=20) {
if (number <= 45) {
switch (number) {
case 20:
return 'a';
case 21:
return 'b';
case 22:
return 'c';
case 23:
return 'd';
case 24:
return 'e';
case 25:
return 'f';
case 26:
return 'g';
case 27:
return 'h';
case 28:
return 'i';
case 29:
return 'j';
case 30:
return 'k';
case 31:
return 'l';
case 32:
return 'm';
case 33:
return 'n';
case 34:
return 'o';
case 35:
return 'p';
case 36:
return 'q';
case 37:
return 'r';
case 38:
return 's';
case 39:
return 't';
case 40:
return 'u';
case 41:
return 'v';
case 42:
return 'w';
case 43:
return 'x';
case 44:
return 'y';
case 45:
return 'z';
}
}
}
throw new InvalidCharException();
}
public static void main(String [] args){
try {
System.out.println(Stuff.getCharacterFromNumber('!'));
} catch (InvalidCharException e) {
e.printStackTrace();
}
System.out.println(Character.getNumericValue('!'));
}
}
i have searched but havent found anything similar to my problem, and if someone has a better idea for the title i'd appricate it :)
Character literals are nothing more than pure values, but with different types. 48 represents exactly the same value as '0' (though the first one is of a type int and the second one is of a type char). 49 also represents the same value as '1'. That's why 'a' + 1 will result in a value equal to 'b'.
What you are confused about is why this:
System.out.println(Character.getNumericValue('!'));
prints -1. Well, to find out why, let's jump into java docs. We can see that the method Character.getNumericValue:
Returns the int value that the specified character (Unicode code point) represents.
It does not return the Unicode value of a character. If you want to see what number represents the character literal '!' you might want to do it like so:
System.out.println((int)'!');
Which will print: 33.
The character '!' has an ASCII value of 33. Java allows for a char value to be widened to an int, which explains why you can pass a char into a method expecting an int.
However, Character.getNumericValue does something different.
Returns the int value that the specified Unicode character represents.
(bold emphasis mine)
That is '1' returns 1, whereas the ASCII code is 49. If the character doesn't represent a numeric value:
If the character does not have a numeric value, then -1 is returned.
You get 2 different values because the ASCII code and the numeric value are two different concepts.
In a switch statement in java, is it necessary that the "default" case be the last one? For example, can I do something like the following:
switch(x) {
case A: ....;
default: ....;
case B: ....;
}
No.. But it is suggested to put it at the end to make the code more readable. The code shown below works fine.
public static void main(String[] args) {
int i = 5;
switch (i) {
default:
System.out.println("hi");
break;
case 0:
System.out.println("0");
break;
case 5:
System.out.println("5");
break;
}
}
O/P : 5
no, the default statement could also be the first one.
It surely is not necessary, but beware it will behave a lot differently in case fall-through is used.
int[] test = {0,1,5,23,24};
for (int t: test) {
System.out.println(String.format("Running test: %s", t));
switch(t) {
case 0:
System.out.println(String.format("Match: %s", 0));
default:
System.out.println(String.format("Match: %s", "default"));
case 23:
System.out.println(String.format("Match: %s", 23));
}
}
Prints:
Running test: 0
Match: 0
Match: default
Match: 23
Running test: 1
Match: default
Match: 23
Running test: 5
Match: default
Match: 23
Running test: 23
Match: 23
Running test: 24
Match: default
Match: 23
This simply speaking means:
if there is an exact (non-default) case defined after default case it is matched first instead of the default one
if there is not, then the default case understandably makes all tested values fall through from itself down
Observe especially the test for 23 - the result would be different if case 23 and default was swapped (both will be matched then).
Demo: https://ideone.com/LyvjXQ
The default statement can be placed anywhere inside switch statement body
switch (i) {
// the default statement can be placed anywhere inside the switch statement body
}
I would like to know is there any difference in performance between these two codes.
String sample="hello";
if(sample!=null)
{
if(!sample.equals(""))
{
// some code in here
}
}
or
String sample="hello";
if(sample!=null && !sample.equals(""))
{
// some code in here
}
As far as i have understood, in the first code, if sample is not null then only it will go in to the block. same is the case with 2nd piece of code.
What i would like to know is what is the difference in performance or better coding standards and why?
If you're asking about performance you should always measure. But No, there shouldn't be a difference. Besides, if that is your only performance-problematic code then I envy you, seriously.
As for coding standards. Less nesting is almost always nicer to read and follow. Which means that putting both in a single if, especially since they are related is preferrable. The pattern
if (check_foo_for_null && compare_foo)
is very common and thus much less surprising than another nested if.
EDIT: To back it up:
I have the two little methods:
static boolean x(String a) {
if (a != null && a.equals("Foo"))
return true;
else return false;
}
static boolean y(String a) {
if (a != null) {
if (a.equals("Foo")) {
return true;
} else return false;
} else return false;
}
which produce the following code:
static boolean x(java.lang.String);
Code:
0: aload_0
1: ifnull 15
4: aload_0
5: ldc #16 // String Foo
7: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
10: ifeq 15
13: iconst_1
14: ireturn
15: iconst_0
16: ireturn
static boolean y(java.lang.String);
Code:
0: aload_0
1: ifnull 17
4: aload_0
5: ldc #16 // String Foo
7: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
10: ifeq 15
13: iconst_1
14: ireturn
15: iconst_0
16: ireturn
17: iconst_0
18: ireturn
So apart from an extraneous else jump target the code is identical. If you don't even have the else:
static boolean z(String a) {
if (a != null) {
if (a.equals("Foo"))
return true;
return false;
}
then the result is really the same:
static boolean z(java.lang.String);
Code:
0: aload_0
1: ifnull 15
4: aload_0
5: ldc #16 // String Foo
7: invokevirtual #21 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
10: ifeq 15
13: iconst_1
14: ireturn
15: iconst_0
16: ireturn
As everyone else said, there shouldn't be any difference in preformance.
Small tip - equals almost always calls instanceof which returns false for null.
So writing:
if( !"".equals(foo)) {...}
does same check and is null-safe.
Bothe have no difference in terms of performance. Because in first case it checks one condition, if fails it does not enter inside. In 2nd case also, JVM checks the first condition, if it return false, then JVM will never go for 2nd check. As logical && operator will always false if first is false.
In terms of coding standard, I will choose 2nd option, as it has less number of coding lines.
Most likely the bytcode generated will be optimized to if(sample!=null && !sample.equals("")) since java performs an optimization in compile time.
If you are talking about the actual code you write it is better to have only one if. Since the structure of two if is more complex for the compiler (with no optimization). Although I have no empiric data to back this.
I have decompiled a very simple class that uses the new Java 7 String Switch feature.
The class:
public class StringSwitch {
public static void main(String[] args) {
final String color = "red";
switch (color) {
case "red":
System.out.println("IS RED!");
break;
case "black":
System.out.println("IS BLACK");
break;
case "blue":
System.out.println("IS BLUE");
break;
case "green":
System.out.println("IS GREEN");
break;
}
}
}
Running the Java 7 "javap" against this class, generates an interesting set of instructions (the complete disassembled code is available here):
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=4, args_size=1
...
12: lookupswitch { // 4
112785: 56
3027034: 84
93818879: 70
98619139: 98
default: 109
}
56: aload_2
57: ldc #2 // String red
...
110: tableswitch { // 0 to 3
0: 140
1: 151
2: 162
3: 173
default: 181
}
140: getstatic #8 // Field java/lang/System.out:Ljava/io/PrintStream;
143: ldc #9 // String IS RED!
...
181: return
The "LOOKUPSWITCH" is an instruction used when the switch case is sparse and can replace the TABLESWITCH, that is the default instruction for "switch" statements.
So, the question is, why are we seeing a "LOOKUPSWITCH" followed by a "TABLESWITCH"?
Thanks
Luciano
With strings in switch finding the correct case statement is a 2 step process.
Compute the hashcode of the switch string and look for a 'hashcode match' among the case statements, this is done via LOOKUPSWITCH. Note the large integer numbers under LOOKUPSWITCH, these are hashcodes of the strings in case statements.
Now 2 strings can have the same hashcode, however unlikely it may be. Hence the actual string comparison must still take place. Hence once the hashcode is matched, the switch string is compared with the string in the matched case statement. The instructions between LOOKUPSWITCH and TABLESWITCH do exactly this. Once the match is confirmed, the code to be executed for the matched case statement is reached via TABLESWITCH.
Also note that it is useful to specify which compiler you used - javac or ECJ (Eclipse compiler for java). Both compilers may generate the bytecode differently.
Greetings,
Let's say you wanted to test a string to see if it's an exact match, or, if it's a match with an _ and any number of characters appended following the _
Valid match examples:
MyTestString
MyTestString_
MyTestString_1234
If performance was a huge concern, which methods would you investigate? Currently I am doing the following:
if (String.equals(stringToMatch)) {
// success
} else {
if (stringToMatch.contains(stringToMatch + "_")) {
// success
}
// fail
}
I tried replacing the pattern the String.contains _ with a Java.util.regex.Pattern match on _*, but that performed much worse. Is my solution here ideal or can you think of something more cleaver to improve performance a bit more?
Thanks for any thoughts
You can do something like
if(string.startsWith(testString)) {
int len = testString.length();
if(string.length() == len || string.charAt(len) == '_')
// success
}
I assume you want the testString to appear even if you have a "_"?
EDIT: On whether to use one long condition or nested if statements, there is no difference in code or performance.
public static void nestedIf(boolean a, boolean b) {
if (a) {
if (b) {
System.out.println("a && b");
}
}
}
public static void logicalConditionIf(boolean a, boolean b) {
if (a && b) {
System.out.println("a && b");
}
}
compiles to the same code. If you do javap -c
public static void nestedIf(boolean, boolean);
Code:
0: iload_0
1: ifeq 16
4: iload_1
5: ifeq 16
8: getstatic #7; //Field java/lang/System.out:Ljava/io/PrintStream;
11: ldc #8; //String a && b
13: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: return
public static void logicalConditionIf(boolean, boolean);
Code:
0: iload_0
1: ifeq 16
4: iload_1
5: ifeq 16
8: getstatic #7; //Field java/lang/System.out:Ljava/io/PrintStream;
11: ldc #8; //String a && b
13: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: return
The complied code is identical.
You could use regular expressions to match patterns. You can use stringToMatch.matches(".*?_.*?"). This returns a boolean.
I ran some benchmarks. This is the quickest I can get.
String a = "Test123";
String b = "Test123_321tseT_Test_rest";
int len1 = a.length();
int len2 = b.length();
if ((len1 == len2 || (len2 > len1 && (b.charAt(len1)) == '_'))
&& b.startsWith(a)) {
System.out.println("success");
} else {
System.out.println("Fail");
}
This will at least work correctly at reasonable performance.
Edit: I switched the _ check and the startsWith check, since startsWith will have worse perforam the _ check.
Edit2: Fixed StringIndexOutOfBoundsException.
Edit3: Peter Lawrey is correct that making only 1 call to a.length() spares time. 2.2% in my case.
Latest benchmark shows I'm 88% faster then OP and 10% faster then Peter Lawrey's code.
Edit4: I replace all str.length() with a local var, and ran dozen more benchmarks. Now the results of the benchmarks are getting so random it's impossible to say what code is faster. My latest version seems to win by a notch.