Validate a String to see if it is an Integer? - java

Not keen on using the parseInteger solution, it is ugly, and as Joshua Bloch says you should "Use exceptions only for exceptional conditions". Of course, I can use something like block of code below, but it doesn't guarantee it is an Integer.
for (char c : str.toCharArray())
{
if (!Character.isDigit(c)) return false;
}
return true;

"Use exceptions only for exceptional conditions" is a good practice to follow in general, but it's not a hard-and-fast rule. I think that this is one of the cases where using exceptions is better than the alternatives.
Since parseInteger() can return any possible int value, you can't use any other return value to indicate failure. If you know you're never going to process a particular value (such as -1 or -2147483648), you can return that as a sentinel value to indicate a parse failure.
The only alternative is to return a boolean indicating success or failure and to store the parsed value into a parameter. However, since function calls are always pass-by-value in Java, you'd need to create a new class to do this:
public class IntWrapper
{
int value;
}
...
public static boolean myParseInt(String s, IntWrapper outValue)
{
try
{
outValue.value = Integer.parseInt(s);
return true;
}
catch(NumberFormatException e)
{
return false;
}
}
...
IntWrapper value = new IntWrapper();
if (myParseInt(value))
{
// Use value.value
}
else
{
// Parsing failed
}
Given these alternatives, I think the simplest usage is just to use exceptions and deal with them appropriately, even though non-numeric input may not necessary be an "exceptional" condition.

I'd leave it with exception but if you REALLY want solution without exception you can copy method parseInt() from this site with java internal classes and change it a little bit
(You can modify it a little bit more, since you do not need result)
public static false isValidInt(String s, int radix)
throws NumberFormatException
{
if (s == null) {
return false;
}
if (radix < Character.MIN_RADIX) {
return false;
}
if (radix > Character.MAX_RADIX) {
return false;
}
int result = 0;
boolean negative = false;
int i = 0, len = s.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
char firstChar = s.charAt(0);
if (firstChar < '0') { // Possible leading "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else
return false;
if (len == 1) // Cannot have lone "-"
return false;
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(s.charAt(i++),radix);
if (digit < 0) {
return false;
}
if (result < multmin) {
return false;
}
result *= radix;
if (result < limit + digit) {
return false;
}
result -= digit;
}
} else {
return false;
}
return true;
}

You could use:
public static boolean isInteger(String str) {
if (str == null) {
return false;
}
int length = str.length();
if (length == 0) {
return false;
}
int i = 0;
if (str.charAt(0) == '-') {
if (length == 1) {
return false;
}
i = 1;
}
for (; i < length; i++) {
char c = str.charAt(i);
if (c <= '/' || c >= ':') {
return false;
}
}
return true;
}
Already answered here: What's the best way to check to see if a String represents an integer in Java?

Related

What am I doing wrong in this loop?

So for I am trying to make a boolean method that checks if an inputed string is a positive integer. It will return true if it is a positive integer and false if it is anything else. Here is my code:
public static boolean isPositiveInteger(String input) {
int stringLength = input.length();
int index = stringLength-1;
while(index>0) {
index--;
if(input.charAt(0) != '-' && input.charAt(index) >= '0' &&
input.charAt(index) <= '9') {
return true;
}
return false;
}
return false;
}
When the input is the string "fish33" the method will return true instead of false. Why is that?
Your while loop executes only once - return will stop execution. Moreover, you start with second to last, not with last character. Replace your code with this one:
public static boolean isPositiveInteger(String input) {
int stringLength = input.length();
int index = stringLength;
// special case when input is empty string
if (index == 0) {
return false;
}
while(index > 0) {
index--;
// if some of the characters is not digit, return false
if !(input.charAt(index) >= '0' &&
input.charAt(index) <= '9') {
return false;
}
}
// if the while loop does not find any other character, return true
return true;
}
There is no point to make so many manipulations, it can be solved in few lines
public static void main(String[] args) {
System.out.println(isPositiveInteger("1"));
System.out.println(isPositiveInteger("abc"));
}
public static boolean isPositiveInteger(String input) {
try {
Integer i = Integer.parseInt(input);
return i > 0;
}
catch(NumberFormatException nfe){
return false;
}
}

To check if string is palindrome using recursion?

There is something wrong with my code as one the testcase in my assignment is coming out wrong, giving me runtime error when I submit the code online. That testcase could be any String. I believe that everything is fine with the code as I have checked it manually for many testcases.
HERE IS THE CODE
public static boolean isStringPalindrome(String input) {
if(input.length()==0 || input.length()==1)
return true;
int first = 0;
int last = input.length()-1;
if(input.charAt(first) != input.charAt(last))
return false;
String str="";
for(int i=first+1;i<last;i++){
str = str+input.charAt(i);
}
boolean sa = isStringPalindrome(str);
return sa;
}
Sample Input
racecar
Output
true
Sample Input
pablo
Output
false
Your code appears to be overly complicated for recursively testing if the String is a palindrome. Something like,
public static boolean isStringPalindrome(String input) {
if (input == null) {
return false;
} else if (input.isEmpty() || input.length() == 1) {
return true;
}
int len = input.length() - 1;
return input.charAt(0) == input.charAt(len) //
&& isStringPalindrome(input.substring(1, len));
}
Is recursive without embedding a for loop. Because if you can do that, you should do something like
public static boolean isStringPalindrome(String input) {
if (input == null) {
return false;
} else if (input.isEmpty() || input.length() == 1) {
return true;
}
int len = input.length();
for (int i = 0; i <= len / 2; i++) {
if (input.charAt(i) != input.charAt(len - 1 - i)) {
return false;
}
}
return true;
}
A simpler way to check for palindrome can be:
public static boolean isPalindrome(String s)
{ if (input == null)
return false;
else if(s.length() == 0 || s.length() == 1)
return true;
/* check for first and last char of String:
* if they are same then do the same thing for a substring
* with first and last char removed. and carry on this
* until you string completes or condition fails.
*/
if(s.charAt(0) == s.charAt(s.length()-1))
return isPalindrome(s.substring(1, s.length()-1));
return false;
}
Update
You are getting runtime error(NZEC) which means non-zero exit code. It means your program is ending unexpectedly. I don't see any reason except that your program doesn't have a null check. Otherwise, I have gone through your code carefully, you are doing the same thing which I have suggested.

Why does this code throw exception - Comparison method violates its general contract

I am using the following code that is throwing a IllegalArgumentException :
// Copyright (c) 2003-2014, Jodd Team (jodd.org). All Rights Reserved.
package jodd.util;
import java.util.Comparator;
/**
* Compares two strings in natural, alphabetical, way.
*/
public class NaturalOrderComparator<T> implements Comparator<T> {
protected final boolean ignoreCase;
public NaturalOrderComparator() {
ignoreCase = false;
}
public NaturalOrderComparator(boolean ignoreCase) {
this.ignoreCase = ignoreCase;
}
/**
* Compare digits at certain position in two strings.
* The longest run of digits wins. That aside, the greatest
* value wins.
*/
protected int compareDigits(String str1, int ndx1, String str2, int ndx2) {
int bias = 0;
while (true) {
char char1 = charAt(str1, ndx1);
char char2 = charAt(str2, ndx2);
boolean isDigitChar1 = CharUtil.isDigit(char1);
boolean isDigitChar2 = CharUtil.isDigit(char2);
if (!isDigitChar1 && !isDigitChar2) {
return bias;
}
if (!isDigitChar1) {
return -1;
}
if (!isDigitChar2) {
return 1;
}
if (char1 < char2) {
if (bias == 0) {
bias = -1;
}
} else if (char1 > char2) {
if (bias == 0) {
bias = 1;
}
} else if (char1 == 0 && char2 == 0) {
return bias;
}
ndx1++;
ndx2++;
}
}
public int compare(T o1, T o2) {
String str1 = o1.toString();
String str2 = o2.toString();
int ndx1 = 0, ndx2 = 0;
int zeroCount1, zeroCount2;
char char1, char2;
int result;
while (true) {
// only count the number of zeroes leading the last number compared
zeroCount1 = zeroCount2 = 0;
char1 = charAt(str1, ndx1);
char2 = charAt(str2, ndx2);
// skip over leading spaces or zeros in both strings
while (Character.isSpaceChar(char1) || char1 == '0') {
if (char1 == '0') {
zeroCount1++;
} else {
zeroCount1 = 0; // counts only last 0 prefixes, space char interrupts the array of 0s
}
ndx1++;
char1 = charAt(str1, ndx1);
}
while (Character.isSpaceChar(char2) || char2 == '0') {
if (char2 == '0') {
zeroCount2++;
} else {
zeroCount2 = 0;
}
ndx2++;
char2 = charAt(str2, ndx2);
}
// process digits
boolean isDigitChar1 = CharUtil.isDigit(char1);
boolean isDigitChar2 = CharUtil.isDigit(char2);
if (isDigitChar1 && isDigitChar2) {
result = compareDigits(str1, ndx1, str2, ndx2);
if (result != 0) {
// not equals, return
return result;
}
// equal numbers
if (zeroCount1 != zeroCount2) {
return zeroCount1 - zeroCount2;
}
}
if (char1 == 0 && char2 == 0) {
// the end; the strings are the same, maybe compare ascii?
return zeroCount1 - zeroCount2;
}
// check when one of the numbers is just zeros
if (isDigitChar1 || isDigitChar2) {
if (zeroCount1 != zeroCount2) {
return zeroCount2 - zeroCount1;
}
}
// checks when both numbers are zero
if (zeroCount1 != zeroCount2) {
return zeroCount1 - zeroCount2;
}
// compare chars
if (ignoreCase) {
char1 = Character.toLowerCase(char1);
char2 = Character.toLowerCase(char2);
}
if (char1 < char2) {
return -1;
}
if (char1 > char2) {
return 1;
}
ndx1++;
ndx2++;
}
}
/**
* Safe charAt.
*/
private static char charAt(String s, int i) {
if (i >= s.length()) {
return 0;
}
return s.charAt(i);
}
}
throws the exception:
java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeLo(TimSort.java:747)
at java.util.TimSort.mergeAt(TimSort.java:483)
at java.util.TimSort.mergeCollapse(TimSort.java:410)
at java.util.TimSort.sort(TimSort.java:214)
at java.util.TimSort.sort(TimSort.java:173)
at java.util.Arrays.sort(Arrays.java:659)
at java.util.Collections.sort(Collections.java:217)
This is called by the following function:
#Override
public int compare(final T o1, final T o2) {
int result;
final MyObject obj1 = (MyObject) o1;
final MyObject obj2 = (MyObject) o2;
return result = compareStringId(obj1.getStringId(),obj2.getStringId());
}
private int compareStringId(final String Id1, final String Id2) {
return super.compare((T) Id1, (T) Id2);
}
It work fine on our local machines, however it fails on production and we have no means to connect to that machine to figure out why. Could you please assist
The issue was with the incorrect implementation of a Comparator. According to Java documentation, a Comparator must be both reflexive and transitive. In this case, the transivity was not guaranteed. Prior Java 8 that was not a big issue, i.e. the sorting implementation (MergeSort) would not throw exception. Java8 changed default sorting implementation to TimSort that is much more sensitive to comparators with invalid contract, hence it might throw an exception.
However, this does not help you much in solving your issue. How about to check the latest version of the same class here. It has been upgraded to support the comparator contract, plus it works better on some edge cases, not to mention initial support for accents.

Trying to return true if all the letters in a string are the same

What I have so far:
public boolean allSameLetter(String str)
{
for (int i = 1; i < str.length(); i++)
{
int charb4 = i--;
if ( str.charAt(i) != str.charAt(charb4))
{
return false;
}
if ( i == str.length())
{
return true;
}
}
}
Please excuse any inefficiencies if any; still relatively new to coding in general. Am I lacking some knowledge in terms of using operators and .charAt() together? Is it illogical? Or is my error elsewhere?
Using regex:
return str.matches("^(.)\\1*$");
Using streams:
str.chars().allMatch(c -> c == str.charAt(0));
Other:
return str.replace(String.valueOf(str.charAt(0), "").length() == 0;
You can follow the below steps:
(1) Get the first character (i.e., 0th index)
(2) Check the first character is the same with subsequent characters, if not return false (and comes out from method)
(3) If all chars match i.e., processing goes till the end of the method and returns true
public boolean allSameLetter(String str) {
char c1 = str.charAt(0);
for(int i=1;i<str.length;i++) {
char temp = str.charAt(i);
if(c1 != temp) {
//if chars does NOT match,
//just return false from here itself,
//there is no need to verify other chars
return false;
}
}
//As it did NOT return from above if (inside for)
//it means, all chars matched, so return true
return true;
}
As Andrew said, you are decreasing i within your for loop. You can fix this by changing it to int charb4 = i - 1;. As for making your code more efficient you could condense it down to this.
public boolean allSameLetter(String str) {
for(char c : str.toCharArray())
if(c != str.charAt(0)) return false;
return true;
}
Comment if you don't understand a part of it :)
public boolean allSameLetter(String str)
{
for (int i = 1; i < str.length() -1; i++)
{
if ( str.charAt(i) != str.charAt(i+1))
{
return false;
}
}
return true
}
-1 is there since I am checking the current value in the array, then the next value in the array, thus I need to stop a place earlier.
If the loop if statement is never entered, it will make it far enough into the code to return true
You have to create a for loop that searches through the length of the String - 1. this way the program will not crash because of a 3 letter word with the program trying to get the 4th letter. This is what works for me:
public boolean allSameLetter(String str)
{
for(int i = 0; i< str.length()-1; i++){
if (str.charAt(i) != str.charAt(i+1)){
return false;
}
}
return true;
}
if((new HashSet<Character>(Arrays.asList(s.toCharArray()))).size()==1)
return true;
return false;
This should be enough
The bug is caused by
int charb4 = i--;
this line is equal to
int charb4 = i-1;
i=i-1;
Because of this, your loop will never stop.
The easiest way to fix this
public boolean allSameLetter(String str)
{
for (int i = 1; i < str.length(); i++)
{
if ( str.charAt(i) != str.charAt(i-1))
{
return false;
}
}
}

Can't figure out how to fix my code

Hi for the past few hours i have been trying to fix my code. The problem is that when I go to check if "" is an integer is returns true when it should be false. I know why this is happening, it is because it doesn't enter the for loop and returns true , but I can't seem to figure out how to make it return false for "". I can provide more info if needed.
public boolean isInteger(String str)
{
for (int x = 0, n = str.length(); x < n; x++)
{
char c = str.charAt(x);
if (c < '0' || c > '9')
{
if (c != 0 || c != '-')
{
return false;
}
}
}
return true;
}
Thank you for spending your time on trying to help me :)
You could check valid input (ie, a string with length = 0) and return false before you ever try the loop. You're correct, though, it's not entering the loop and just returning true.
--edit--
Something like
if (string == null) || (string.length() == 0){
return false
}
In your algorithm, an empty string will always return true. You just need to add a check:
if(str==null || str.length()==0) return false;
Alternatively, you can use this function:
public static boolean isInteger(String str)
{
try
{
Integer.parseInt(str);
return true;
}
catch(NumberFormatException e)
{
return false;
}
}

Categories

Resources