How could this Java method be improved? - java

I am parsing XML files and I have several methods similar to:
public static Integer getInteger(Object integer) {
if (integer == null) {
return 0;
}
try {
return Integer.parseInt(integer.toString(), 10);
} catch (Exception ex) {
return 0;
}
}
So basically, you pass an object in with the assumption of converting it to an Integer (I also have versions for Float, etc).
This seems to work well but being a Java newbie, I was wondering how you would improve it. I am especially interesting in the boxing/unboxing aspect (at least, from a C# developer's perspective).
Thanks
EDIT
Sorry, I wasn't clear to what goes into the method. Yes, it's for an XML file now so it's always a string. But the string could be empty or maybe even null. I guess I wanted to always return a 0 if there was an error of any kind.

You shouldn't generally catch Exception. Catching NumberFormatException would be more appropriate here.
Any reason for converting to Integer instead of int? Why not let the caller perform the boxing conversion if they need it?

You don't say whether integer is an instance of Integer or not. If it is you can just cast it:
Integer i = (Integer) integer;
having checked for null and instanceof first.
If it is not an instance of Integer then what you're doing seems reasonable, although you only need to catch a NumberFormatException.

You should use instanceof operator, then make safe casting (so if Object integer is instanceof Integer, cast it).
Then you don't have to catch Exception (which in this case is unchecked NumberFormatException)
public static Integer getInteger(Object integer) {
if (integer == null) {
return 0;
}
if (integer instanceof Integer) {
return (Integer)integer;
}
return 0;
}
EDIT
If data is coming from XML, then it will of course never be Integer :) Then parsing from String is required still, so see other answers.

As Jon hinted, returning int (the primitive data type) instead of Integer (the wrapper class) would probably be better (assuming you never want to return null).
Also, adding this code could be a shortcut, when the input is often an Integer object or other Number subclass (I'm calling the input input because it's too confusing otherwise):
if (input instanceof Number) {
return ((Number) integer).intValue();
}

Returning Integer makes sense if you want to signal, that a value is empty. You're testing that already but you shouldn't return 0, unless you have a very clear and somewhat special requirement to do so. No value is not equal to 0.

Also, you can add more special cases besides null, like check for empty string:
public static Integer getInteger(Object integer) {
if (integer == null) {
return 0;
}
try {
String s = integer.toString();
if (s.isEmpty())
return 0;
return Integer.parseInt(s, 10);
} catch (Exception ex) {
return 0;
}
}
On the other side, you can cut all special cases, and go with only:
public static Integer getInteger(Object integer) {
try {
return Integer.parseInt(integer.toString(), 10);
} catch (Exception ex) {
return 0;
}
}
In the end, performance gains (or losses) depends on what portion of your input data is null, empty, unparsable integers, or "normal" integer strings.

Related

Can we combine two methods that differ largely based on type?

I have two similar, but of different types, blocks of code in Java:
private Integer readInteger() {
Integer value = null;
while (value == null) {
if (scanner.hasNextInt()) {
value = scanner.nextInt();
} else {
scanner.next();
}
}
return value;
}
private Double readDouble() {
Double value = null;
while (value == null) {
if (scanner.hasNextDouble()) {
value = scanner.nextDouble();
} else {
scanner.next();
}
}
return value;
}
Is it possible to make just one method which would work for both of them?
I'd say, use a generic method, combined with the functional interfaces introduced in Java 8.
The method read now becomes a higher order function.
private <T> T read(Predicate<Scanner> hasVal, Function<Scanner, T> nextVal) {
T value = null;
while (value == null) {
if (hasVal.test(scanner)) {
value = nextVal.apply(scanner);
} else {
scanner.next();
}
}
return value;
}
Calling code becomes:
read(Scanner::hasNextInt, Scanner::nextInt);
read(Scanner::hasNextDouble, Scanner::nextDouble);
read(Scanner::hasNextFloat, Scanner::nextFloat);
// ...
So the readInteger() method can be adapted as follows:
private Integer readInteger() {
return read(Scanner::hasNextInt, Scanner::nextInt);
}
You could have something with three methods:
One which says if there is a value of the right type
Another which gets the value of the right type.
Another which discards whatever token you have.
For example:
interface Frobnitz<T> {
boolean has();
T get();
void discard();
}
You can pass this into your method:
private <T> T read(Frobnitz<? extends T> frob) {
T value = null;
while (value == null) {
if (frob.has()) {
value = frob.get();
} else {
frob.discard();
}
}
return value;
}
And then just implement Frobnitz for your Double and Integer cases.
To be honest, I'm not sure this gets you very much, especially if you've only got two cases; I'd be inclined just to suck up the small amount of duplication.
A lot of people have answered that you can use generics, but you can also simply remove the readInteger method, and only use the readDouble, as integers can be converted to doubles without data loss.
This is about code duplication.
The general approach is to turn similar code (you have) into equal code that can be extracted to a common parameterized method.
In your case what make the two code snipped differ is the access to methods of Scanner. You have to encapsulate them somehow. I'd suggest to do this with Java8 Functional interfaces like this:
#FunctionalInterface
interface ScannerNext{
boolean hasNext(Scanner scanner);
}
#FunctionalInterface
interface ScannerValue{
Number getNext(Scanner scanner);
}
Then replace the actual invocation of methods in scanner with the functional interface:
private Integer readInteger() {
ScannerNext scannerNext = (sc)->sc.hasNextInt();
ScannerValue scannerValue = (sc)-> sc.nextInt();
Integer value = null;
while (value == null) {
if (scannerNext.hasNext(scanner)) {
value = scannerValue.getNext(scanner);
} else {
scanner.next();
}
}
return value;
}
There is one more problem that the type of the value variable differs. So we replace it with its common supertype:
private Integer readInteger() {
ScannerNext scannerNext = (sc)->sc.hasNextInt();
ScannerValue scannerValue = (sc)-> sc.nextInt();
Number value = null;
while (value == null) {
if (scannerNext.hasNext(scanner)) {
value = scannerValue.getNext(scanner);
} else {
scanner.next();
}
}
return (Integer)value;
}
Now you have to places with a big equal section. You can select one of those sections starting with Number value = null; ending with the } before return ... and invoke your IDEs automated refactoring extract method:
private Number readNumber(ScannerNext scannerNext, ScannerValue scannerValue) {
Number value = null;
while (value == null) {
if (scannerNext.hasNext(scanner)) {
value = scannerValue.getNext(scanner);
} else {
scanner.next();
}
}
return value;
}
private Integer readInteger() {
return (Integer) readNumber( (sc)->sc.hasNextInt(), (sc)-> sc.nextInt());
}
private Double readDouble() {
return (Double) readNumber( (sc)->sc.hasNextDouble(), (sc)-> sc.nextDouble());
}
Comments argue against the use of custom interfaces against predefined interfaces from the JVM.
But my point in this answer was how to turn similar code into equal code so that it can be extracted to a single method rather that giving a concrete solution for this random problem.
Not an ideal solution but it still achieves the necessary removal of duplicate code and has the added benefit of not requiring Java-8.
// This could be done better.
static final Scanner scanner = new Scanner(System.in);
enum Read{
Int {
#Override
boolean hasNext() {
return scanner.hasNextInt();
}
#Override
<T> T next() {
return (T)Integer.valueOf(scanner.nextInt());
}
},
Dbl{
#Override
boolean hasNext() {
return scanner.hasNextDouble();
}
#Override
<T> T next() {
return (T)Double.valueOf(scanner.nextDouble());
}
};
abstract boolean hasNext();
abstract <T> T next();
// All share this method.
public <T> T read() {
T v = null;
while (v == null) {
if ( hasNext() ) {
v = next();
} else {
scanner.next();
}
}
return v;
}
}
public void test(String[] args) {
Integer i = Read.Int.read();
Double d = Read.Dbl.read();
}
There are some minor issues with this such as the casting but it should be a reasonable option.
A totally different approach from my other answer (and the other answers): don't use generics, but instead just write the methods more concisely, so you don't really notice the duplication.
TL;DR: rewrite the methods as
while (!scanner.hasNextX()) scanner.next();
return scanner.nextX();
The overall goal - write it as a single method - is only possible if you accept some amount of additional cruft.
Java method signatures do not take into account the return type, so it's not possible to have a next() method return an Integer in one context, and Double in another (short of returning a common supertype).
As such, you have to have something at the call sites to distinguish these cases:
You might consider passing something like Integer.class or Double.class. This does have the advantage that you can use generics to know that the returned value matches that type. But callers could pass in something else: how would you handle Long.class, or String.class? Either you need to handle everything, or you fail at runtime (not a good option). Even with a tighter bound (e.g. Class<? extends Number>), you still need to handle more than Integer and Double.
(Not to mention that writing Integer.class and Double.class everywhere is really verbose)
You might consider doing something like #Ward's answer (which I do like, BTW: if you're going to do it with generics, do it like that), and pass in functional objects which are able to deal with the type of interest, as well as providing the type information to indicate the return type.
But, again, you've got to pass these functional objects in at each call site, which is really verbose.
In taking either of these approaches, you can add helper methods which pass the appropriate parameters to the "generic" read method. But this feels like a backwards step: instead of reducing the number of methods to 1, it's increased to 3.
Additionally, you now have to distinguish these helper methods somehow at the call sites, in order to be able to call the appropriate one:
You could have overloads with a parameter of value type, rather than class type, e.g.
Double read(Double d)
Integer read(Integer d)
and then call like Double d = read(0.0); Integer i = read(0);. But anybody reading this code is going to be left wondering what that magic number in the code is - is there any significance to the 0?
Or, easier, just call the two overloads something different:
Double readDouble()
Integer readInteger()
This is nice and easy: whilst it's slightly more verbose than read(0.0), it's readable; and it's way more concise that read(Double.class).
So, this has got us back to the method signatures in OP's code. But this hopefully justifies why you still want to keep those two methods. Now to address the contents of the methods:
Because Scanner.nextX() doesn't return null values, the method can be rewritten as:
while (!scanner.hasNextX()) scanner.next();
return scanner.nextX();
So, it's really easy to duplicate this for the two cases:
private Integer readInteger() {
while (!scanner.hasNextInt()) scanner.next();
return scanner.nextInt();
}
private Double readDouble() {
while (!scanner.hasNextDouble()) scanner.next();
return scanner.nextDouble();
}
If you want, you could pull out a method dropUntil(Predicate<Scanner>) method to avoid duplicating the loop, but I'm not convinced it really saves you that much.
A single (near-)duplicated line is way less burdensome in your code than all those generics and functional parameters. It's just plain old code, which happens to be more concise (and, likely, more efficient) than "new" ways to write it.
The other advantage of this approach is that you don't have to use boxed types - you can make the methods return int and double, and not have to pay the boxing tax unless you actually need it.
This may not be of advantage to OP, since the original methods do return the boxed type; I don't know if this is genuinely desired, or merely an artefact of the way the loop was written. However, it is useful in general not to create those objects unless you really need them.
Reflection is an alternative if you don't care about performance.
private <T> T read(String type) throws Exception {
Method readNext = Scanner.class.getMethod("next" + type);
Method hasNext = Scanner.class.getMethod("hasNext" + type);
T value = null;
while (value == null) {
if ((Boolean) hasNext.invoke(scanner)) {
value = (T) readNext.invoke(scanner);
} else {
scanner.next();
}
}
return value;
}
Then you call
Integer i = read("Int");

is there a way to validate data by saying "variable != int"

So this is basically what I want my code to say, as to avoid compile error's in the event that the user selects "Tea" instead of using the corresponding integer.
if(appSelection < 1 || appSelection > appetizersArray.length || appSelection != int)
the first two conditions are obviously to catch data that would be out of bounds, but I'm looking for a way to specify that the input needs to be an int.
If the only option is try catch just say so but I'm hoping there's a more elegant solution.
You could use a regular expression. The lower case \\d matches digits and adding a plus means consecutive. So,
String regex = "\\d+";
String[] arr = { "Tea", "123" };
for (String str : arr) {
if (str.matches(regex)) {
System.out.printf("%s is all digits%n", str);
} else {
System.out.printf("%s is NOT all digits%n", str);
}
}
Output is
Tea is NOT all digits
123 is all digits
Is this command-line input? If so, you can use the Scanner class's nextInt method (https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html#nextInt%28%29). If it's coming from a web form, either your library should convert the value to an integer, in which case you already know it's an integer, or it's a string and you can call Integer.parseInt(String). Documentation here: https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#parseInt%28java.lang.String%29
Assuming that the data comes in a String, well, a try/catch is the thing to use, or some function to check if the provided data is a valid integer, like this:
boolean isValidInt(String s) {
try {
Integer.parseInt(s);
} catch (Exception e) {
return false;
}
return true;
}
Then you can say:
if(!isValidInt(appSelection)) someError();
Hope it helps!
Assuming this is a Java-related question, int is a primitive. The operation you are referring to has a operator: instanceof. Unfortunately, it does not work for primitive data types. In order to use this you have to use a wrapper class (i.e Integer). So:
int x = 1;
if (x instanceof Integer) { // compilation error }
Unfortunately, autoboxing does not work for this. What you can do is the following:
String value = ???; // ??? represents some unknown string value.
Later on, you can try to convert that String value to an Integer value:
try
{
Integer x = new Integer(str);
}
catch (NumberFormatException e)
{
// The exception will be thrown if the string does not represent a numeric value. For example: a34bc
}
If the instantiation of variable x succeeds, it will hold a numeric value. Because of Java unboxing mechanism, you will be able to pass 'x' to some method that takes a primitive int. For example:
try
{
Integer x = new Integer(str);
int result = addThisValue(x);
}
catch (NumberFormatException e) {// Do something }
...
public int addThisValue(int value) {...}
You will be able to pass variable x to that method safely.

Convert string to integer- what should I return if string is invalid

If I want to write a function that takes a string and converts it into an integer and I don't trust my input at all, what should I return if the string is invalid. I want to return 0 but would that be confusing since the number might actually be 0? Assume this is for an interview question and you need to check all edge cases.
In Java, it would be conventional to throw an Exception. This is what Integer.parseInt() does, which is the official Java implementation of this functionality.
what should I return if the string is invalid
Throw a RunTimeException. API already does that for you.If your try to parse an invalid string using Integer.parseInt(str) it would throw NumberFormatException at run time.
One possible option is to return default value if string can't be converted to integer. For example:
public int convert(String input, int defaultValue) {
try {
return Integer.parseInt(input);
} catch (Exception e) {
return defaultValue;
}
}

Why is FindBugs complaining here?

public int getFreezeColumns() {
Integer currentValue = (Integer) checkValueBinding("freezeColumns", this.freezeColumns);
if (currentValue != null) {
return currentValue;
}
return 0;
}
FindBugs says :
A primitive is boxed, and then immediately unboxed. This probably is due to a manual boxing in a place where an unboxed value is required, thus forcing the compiler to immediately undo the work of the boxing.
How can I possibly fix this ?
I think the complaint is somewhat misleading: you are not boxing the return value of checkValueBinding which is an Object, but you are casting it to Integer prematurely
Try changing the code to see if it helps you avoid the warning:
public int getFreezeColumns() {
Object currentValue = checkValueBinding("freezeColumns", this.freezeColumns);
if (currentValue != null) {
return (Integer)currentValue;
}
return 0;
}
Seems to me like it's complaining that you are creating an Integer, and then converting it to int right away to return it.
What does checkValueBinding return? Do you really need to wrap it into an Integer?

Does java have a int.tryparse that doesn't throw an exception for bad data? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Java: Good way to encapsulate Integer.parseInt()
how to convert a string to float and avoid using try/catch in java?
C# has Int.TryParse: Int32.TryParse Method (String, Int32%)
The great thing with this method is that it doesn't throw an exception for bad data.
In java, Integer.parseInt("abc") will throw an exception, and in cases where this may happen a lot performance will suffer.
Is there a way around this somehow for those cases where performance is an issue?
The only other way I can think of is to run the input against an regex, but I have to test to see what is faster.
No. You have to make your own like this:
public int tryParseInt(String value, int defaultVal) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return defaultVal;
}
}
...or
public Integer parseIntOrNull(String value) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
return null;
}
}
Apache Commons has an IntegerValidator class which appears to do what you want. Java provides no in-built method for doing this.
See here for the groupid/artifactid.
Code sample: (slightly verbose to show functionality clearly)
private boolean valueIsAndInt(String value) {
boolean returnValue = true;
if (null == new org.apache.commons.validator.routines.IntegerValidator().validate(value)) {
returnValue = false;
}
return returnValue;
}
Edit -- just saw your comment about the performance problems associated with a potentially bad piece of input data. I don't know offhand how try/catch on parseInt compares to a regex. I would guess, based on very little hard knowledge, that regexes are not hugely performant, compared to try/catch, in Java.
Anyway, I'd just do this:
public Integer tryParse(Object obj) {
Integer retVal;
try {
retVal = Integer.parseInt((String) obj);
} catch (NumberFormatException nfe) {
retVal = 0; // or null if that is your preference
}
return retVal;
}

Categories

Resources