sort doubles stored as strings ? - java

Hi is there any way to parse strings into numbers? And is there any way to check if a string is a number or not without breaking the program ? I am thinking about using a try and catch would this be a good idea ?

There's no way to check if a string is parseable or not without trying to parse the string (as any check would have to start trying to interpret the string as a number to do that...). For a half-way check, I guess you could use Regex to check if the string has only digits and periods. You'll have to use a try... catch block aswell, though.
As to how to parse a string into a double, try this:
double dd;
try {
dd = Double.parseDouble(string);
}
catch (NumberFormatException e) {
System.out.println("couldnt not parse the string!");
}

Yes. Double.valueOf(String s) will throw a NumberFormatException if your string can't be parsed to a Double and return the parsed Double otherwise.

I'm assuming you want to sort using one of the assorted built-in sort methods. In that case, you'll need to create a custom Comparator<T>, implementing compare() and equals() that attempts to parse the strings as Double, and on catching an exception, implements some sane default behavior. Make sure to catch the exception within your methods - you should only run into problems if you let the exceptions get out into the Java API code.
As a quick example to get you going:
class DoubleStringComparator implements Comparator<String> {
public int compare(String o1, String o2) {
try {
double d1 = Double.parse(o1);
double d2 = Double.parse(d2);
if d1 > d2 {
return 1;
} else if d1 < d2 {
return -1;
else {
return 0;
}
} catch (NumberFormatException e) {
// whatever ordering you want to impose when one string is not a double
}
}
// some definition of equals() - whatever makes sense for your application
}
Then, when you want to do the sorting:
Collections.sort(someListOfString, new DoubleStringComparator());

Take a look at parseDouble
http://download.oracle.com/javase/6/docs/api/java/lang/Double.html#parseDouble%28java.lang.String%29
and yes you can catch NumberFormatException to determine when the number wasn't valid.

You can use regex to find if the strings is double or not
if(num1.matches(("((-|\\+)?[0-9]+(\\.[0-9]+)?)+"))){
isDoubleVal =true;
}else{
isDoubleVal = false;
}
Hope it helps you.
Regards,
Lav

Related

Saxon-HE Java Extension - How to I access the value of a xsl-variable which is passed as a parameter?

I have created a function using the Saxon documentation which has 3 parameters. The function takes an input string and pads it out to a specific size using an integer and string values.
padStringLeft(inputStr,size,padChar)
If I put this in my XSLT and hard wire the parameters the function works.
<debug1><xsl:value-of select="c4j_XSLT_Ext_padStringLeft:padStringLeft('1',4,'0')" /></debug1>
The output from the above would be '0001'
When I pass the contents of a XSLT variable however and set a debug / break point in my java function I can see that I'm getting param0 as a lazysequence.
<debug2><xsl:value-of select="c4j_XSLT_Ext_padStringLeft:padStringLeft($myvar,4,'0')" /></debug2>
Java function
As my code is attempting to treat it as a string it does not work.
How should I be handling this scenario, how do I access the value or the xsl-variable/param and what if sometimes I want to use a literal string instead of a variable?
public class XSLT_Ext_padStringLeft extends ExtensionFunctionDefinition
{
#Override
public SequenceType[] getArgumentTypes()
{
return new SequenceType[]{SequenceType.SINGLE_STRING,SequenceType.SINGLE_INTEGER, SequenceType.SINGLE_STRING};
}
#Override
public StructuredQName getFunctionQName()
{
return new StructuredQName("c4j_XSLT_Ext_padStringLeft", "http://com.commander4j.Transformation.XSLT_Ext_padStringLeft", "padStringLeft");
}
#Override
public SequenceType getResultType(SequenceType[] arg0)
{
return SequenceType.SINGLE_STRING;
}
#Override
public ExtensionFunctionCall makeCallExpression()
{
return new ExtensionFunctionCall() {
#Override
public Sequence call(XPathContext context, Sequence[] arguments) throws XPathException {
String inputStr;
try
{
inputStr = ((StringValue)arguments[0]).getStringValue();
} catch (ClassCastException ex)
{
inputStr = "";
}
long size;
try
{
String temp =arguments[1].toString();
size = Integer.valueOf(temp);
} catch (ClassCastException ex)
{
size = 1;
}
String padStr;
try
{
padStr = ((StringValue)arguments[2]).getStringValue();
} catch (ClassCastException ex)
{
padStr = "";
}
String result = inputStr;
while (result.length() < size)
{
result = padStr + result;
}
return StringValue.makeStringValue(result);
}
};
}
}
Thanks
Dave
In general the parameters are passed as instance of the class net.sf.saxon.om.Sequence, and you should only use the methods on the interface Sequence, rather than examining what particular kind of Sequence it is, because that could change in the future.
If you're expecting a singleton sequence (that is, a single item), call head() to get the first item in the sequence (this will return null if the sequence is empty). You will then have an instance of net.sf.saxon.om.Item. (The Sequence might already be an Item, because an item is a sequence, but you can't rely on that, and calling head() is safer than casting.) If you're expecting a string, you can safely call getStringValue() on this item to get the value as a string.
Also note, Saxon uses lazy evaluation wherever possible, which means that the string might not actually be computed until someone asks for its value. This means that innocent-looking calls like head() and getStringValue() can actually throw exceptions, and you need to be prepared for this.
So in short, you should replace
inputStr = ((StringValue)arguments[0]).getStringValue();
with
inputStr = arguments[0].head().getStringValue();
Also note, Saxon uses lazy evaluation wherever possible, which means that the string might not actually be computed until someone asks for its value. This means that innocent-looking calls like head() and getStringValue() can actually throw exceptions, and you need to be prepared for this.
So if I understand you correctly - when I call Transform to process the XSLT transformation it will call each of my custom java external functions as needed but the reference to
inputStr = arguments[0].head().getStringValue();
could generate an exception?
I would then need to do something within the java function to force it to get the value - or would I let the exception propogate back to the calling Transformation and catch it there ?
Dave

Two digits after dot in toString

I managed to make these two classess, but "score" has to have 7 digits after the dot. I cannot modify Main class. I think I should use String.format("%.7f", ...) but I don't know where. Please help.
MAIN:
public class Main {
public static void main(String[] args) {
Calc c = new Calc();
String score = c.doCalc(args[0]);
System.out.println(score);
}
}
CALC:
public class Calc {
public String doCalc(String cmd) {
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
try {
return engine.eval(cmd).toString();
}
catch (ScriptException e) {
return "Invalid command to calc";
}
}
}
Instead of using system.out.println, you should use system.out.format or system.out.printf. See a short tutorial from Oracle on using it here. Why exactly can't you modify the main class? That seems to be where your score is being printed..
You can parse the string result back to Double and feed it to String.format:
try {
return String.format("%.7f", Double.valueOf(engine.eval(cmd).toString()));
}
catch (Exception e) {
return "Invalid command to calc";
}
You could of course feed the result directly to String.format without the toString and valueOf round trip, like so:
return String.format("%.7f", engine.eval(cmd));
But that only works when the eval result is a valid floating point number. To deal with other cases like integers or non-numbers, you'd have to put in a few type checks and make the code look more cluttered.

How to check Type before casting in java

I am casting my String variables to integer and double. I want to check whether the String variable contains valid Integer or Double value at runtime.
I us following code but it not works for me.
String var1="5.5";
String var2="6";
Object o1=var1;
Object o2=var2;
if (o1 instanceof Integer)
{
qt += Integer.parseInt( var1);// Qty
}
if (o2 instanceof Double)
{
wt += Double.parseDouble(var2);// Wt
}
Try to parse the int and catch the exception if it fails:
String var1="5.5";
try {
qt += Integer.parseInt( var1);
}
catch (NumberFormatException nfe) {
// wasn't an int
}
You can use patterns to detect if a string is an integer or not :
Pattern pattern = Pattern.compile("^[-+]?\\d+(\\.\\d+)?$");
Matcher matcher = pattern.matcher(var1);
if (matcher.find()){
// Your string is a number
} else {
// Your string is not a number
}
You will have to find the correct pattern (I haven't used them for awhile) or someone could edit my answer with the correct pattern.
*EDIT** : Found a pattern for you. edited the code. I did not test it but it is taken from java2s site which also offer an even more elgant approach (copied from the site) :
public static boolean isNumeric(String string) {
return string.matches("^[-+]?\\d+(\\.\\d+)?$");
}
First of all, your if condition will certainly fail, because the object reference actually points to a String object. So, they are not instances of any integer or double.
To check whether a string can be converted to integer or double, you can either follow the approach in #Bedwyr's answer, or if you don't want to use try-catch, as I assume from your comments there (Actually, I don't understand why you don't want to use them), you can use a little bit of pattern matching: -
String str = "6.6";
String str2 = "6";
// If only digits are there, then it is integer
if (str2.matches("[+-]?\\d+")) {
int val = Integer.parseInt(str2);
qt += val;
}
// digits followed by a `.` followed by digits
if (str.matches("[+-]?\\d+\\.\\d+")) {
double val = Double.parseDouble(str);
wt += val;
}
But, understand that, Integer.parseInt and Double.parseDouble is the right way to do this. This is just an alternate approach.
Maybe regexps could suit your needs:
public static boolean isInteger(String s) {
return s.matches("[-+]?[0-9]+");
}
public static boolean isDouble(String s) {
return s.matches("[-+]?([0-9]+\\.([0-9]+)?|\\.[0-9]+)");
}
public static void main(String[] args) throws Exception {
String s1 = "5.5";
String s2 = "6";
System.out.println(isInteger(s1));
System.out.println(isDouble(s1));
System.out.println(isInteger(s2));
System.out.println(isDouble(s2));
}
Prints:
false
true
true
false
Integer.parseInt and Double.parseDouble return the integer/double value of the String. If the String is not a valid number, the method will thrown a NumberFormatException.
String var1 = "5.5";
try {
int number = Integer.parseInt(var1); // Will fail, var1 has wrong format
qt += number;
} catch (NumberFormatException e) {
// Do your thing if the check fails
}
try {
double number = Double.parseDouble(var1); // Will succeed
wt += number;
} catch (NumberFormatException e) {
// Do your thing if the check fails
}

Gson deserialize with null int can't seems to work

When i download data on the web, sometimes it works and sometime it doesn't.
And my problem is in one int :
runtime: ""
runtime is an int and when i use gson on it can cause this problem :
01-07 21:22:57.602: E/AndroidRuntime(2726): Caused by: java.lang.NumberFormatException: Invalid int: ""
and i tried to some if statement but it doesn't work.
public int getRuntime() {
if(Integer.valueOf(runtime)==null){
return 0;
}else{
return runtime;
}
}
or even
public int getRuntime() {
if(Integer.valueOf(runtime).equals(null)){
return 0;
}else{
return runtime;
}
}
but nothing works.
Integer.valueOf() expects a String representing an integer. Calling it with an empty string will lead to an exception. You need to test the String before parsing it as an integer:
int runtime;
if ("".equals(string)) {
runtime = 0;
}
else {
runtime = Integer.parseInt(string);
}
or, if you always want that runtime is 0 if the string is not a valid integer, then catch the exception:
try {
runtime = Integer.parseInt(string);
}
catch (NumberFormatException e) {
runtime = 0;
}
Now, it it's gson that parses the string for you, and this string is not always an integer, then the runtime field should not be an int, but a String. And you should parse it yourself, as shown above.
Given your question, before trying to do anything with gson and android, you should learn the basics of the Java language. You don't seem to understand the type system in Java and what exceptions are. Read http://docs.oracle.com/javase/tutorial/java/nutsandbolts/
Handle the runtime as a string, declare it as a string in the class where you are deserializing.
Then using the gson like this will handle the nulls correctly
Gson gson = new GsonBuilder().serializeNulls().create();
This works also when serializing, normally if values are null it will just not put anything in the json to serialize.
It looks like you don't understand what exceptions are, or how to handle them:
http://docs.oracle.com/javase/tutorial/essential/exceptions
public int getRuntime() {
int i = 0;
try {
i = Integer.valueOf(runtime);
} catch (NumberFormatException e) {
System.out.println("runtime wasn't an int, returning 0");
}
return i;
}
Hint: whatever runtime is, it's not anything that can be converted to an int. From what you posted, it looks like an empty String
You either need to check runtime first, e.g. if( runtime.isEmpty() ) or yet better - using apache commons lang - if( StringUtils.isBlank( runtime )) or catch the NumberFormatException that is thrown.

how to convert a string to float and avoid using try/catch in java?

There are some situation that I need to convert string to float or some other numerical data-type but there is a probability of getting some nonconvertible values such as "-" or "/" and I can't verify all the values beforehand to remove them.
and I want to avoid using try/catch for this matter , is there any other way of doing a proper conversion in java? something similar to C# TryParse?
The simplest thing I can think of is java.util.Scanner . However this approach requires a new Scanner instance for each String.
String data = ...;
Scanner n = new Scanner(data);
if(n.hasNextInt()){//check if the next chars are integer
int i = n.nextInt();
}else{
}
Next you could write a regex pattern that you use to check the String (complex to fail too big values) and then call Integer.parseInt() after checking the string against it.
Pattern p = Pattern.compile("insert regex to test string here");
String data = ...;
Matcher m = p.matcher(data);
//warning depending on regex used this may
//only check part of the string
if(m.matches()){
int i = Integer.parseInt(data);
}
However both of these parse the string twice, once to test the string and a second time to get the value. Depending on how often you get invalid strings catching an exception may be faster.
Unfortunately, there is no such method in Java. There is no out parameter in Java, so writing such a method would need to return a null Float to signal an error, or to pass a FloatHolder object which could be modified by the method:
public class FloatHolder {
private float value;
public void setValue(float value) {
this.value = value;
}
public float getValue() {
return this.value;
}
}
public static boolean tryParseFloat(String s, FloatHolder holder) {
try {
float value = Float.parseFloat(s);
holder.setValue(value);
}
catch (NumberFormatException e) {
return false;
}
}
This is an old question, but since all the answers fail to mention this (and I wasn't aware of it myself until seeing it in a merge request written by a colleague), I want to point potential readers to the Guava Floats and Ints classes:
With the help of these classes, you can write code like this:
Integer i = Ints.tryParse("10");
Integer j = Ints.tryParse("invalid");
Float f = Floats.tryParse("10.1");
Float g = Floats.tryParse("invalid.value");
The result will be null if the value is an invalid int or float, and you can then handle it in any way you like. (Be careful to not just cast it to an int/float, since this will trigger a NullPointerException if the value is an invalid integer/floating point value.)
Note that these methods are marked as "beta", but they are quite useful anyway and we use them in production.
For reference, here are the Javadocs for these classes:
https://google.github.io/guava/releases/snapshot-jre/api/docs/com/google/common/primitives/Ints.html
https://google.github.io/guava/releases/snapshot-jre/api/docs/com/google/common/primitives/Floats.html
Java does not provide some built in tryParse type of methods, on of the solutions you can try is to create your own tryParse Method and put try/catch code in this method and then you can easily use this method across your application very easily and without using try/catch at all the places you use the method.
One of the sample functions can have following code
public static Long parseLong(String value) {
if(isNullOrEmpty(value)) {
return null;
}
try {
return Long.valueOf(value);
}
catch (NumberFormatException e) {
}
return null;
}
Regular expressions helped me solve this issue. Here is how:
Get the string input.
Use the expression that matches one or more digits.
Parse if it is a match.
String s = "1111";
int i = s.matches("^[0-9]+$") ? Integer.parseInt(s) : -1;
if(i != -1)
System.out.println("Integer");
else
System.out.println("Not an integer");

Categories