Can anybody see why here the two "Integers" can't be compared? - java

public String minWindow(String S, String T) {
if (T.length() > S.length())
return "";
HashMap<Character, Integer> set = new HashMap<>();
for (int i = 0; i < T.length(); i++) {
if (!set.containsKey(T.charAt(i))) {
set.put(T.charAt(i), 1);
} else {
set.put(T.charAt(i), set.get(T.charAt(i)) + 1);
}
}
int count = 0;
int min = Integer.MAX_VALUE;
int begin = 0;
int end = 0;
LinkedList<Integer> index = new LinkedList<>();
HashMap<Character, Integer> record = new HashMap<>();
for (int i = 0; i < S.length(); i++) {
Character tmp = S.charAt(i);
if (set.containsKey(tmp)) {
index.add(i);
if (record.containsKey(tmp)) {
record.put(tmp, record.get(tmp) + 1);
} else {
record.put(tmp, 1);
}
int num1 = record.get(tmp);
int num2 = set.get(tmp);
if (num1 == num2) {
count++;
}
if (count == set.size()) {
Character head = S.charAt(index.peek());
while (record.get(head) > set.get(head)) {
record.put(head, record.get(head) - 1);
index.remove();
head = S.charAt(index.peek());
}
if (index.getLast() - index.peek() < min) {
min = index.getLast() - index.peek();
begin = index.peek();
end = index.getLast();
}
}
} else {
continue;
}
}
if (min == Integer.MAX_VALUE) {
return "";
} else {
return S.substring(begin, end + 1);
}
}
This is the my code of one Leetcode problem. But I don't think it involves the algorithm problem. So I post it here. Here it is the problem:
I use a hashmap "record" to record the duplicated characters in S and another one "set" to record the duplicated characters in T. When the number of the duplicated characters equal, plus one to variable "count";
I passed all the test except the last one S is a string of length 100000 and T is a string with length 10001.
I must use this form:
int num1 = record.get(tmp);
int num2 = set.get(tmp);
if (num1 == num2) {
count++;
}
instead of:
if(record.get(tmp)==set.get(tmp)){
count++;
}
Only like this can the two integers be compared or the "count" won't be plused. Why the first 265 test cases can pass but the last large string causes the problem? Thank you in advance.

Because the value of your Maps are Integer. Integer are objects and have to compared using the equals method.
if(record.get(tmp).equals(set.get(tmp))){

an it's an "autoboxing trap", you are putting Integer in record and set. If you call the get method you get two Integer thant must be compared with equals.
When you write
int num1 = record.get(tmp);
2 distinct operations happen
Retrieve the Integer
Convert the Integer to int (so you can use ==)
another trap is with null objects it the Integer is null
int num1 = record.get(tmp);
gives you a NullPointerException

It is returning Integer instead of int as you have HashMap<Character, Integer>, so it is not giving expected output for ==.
You can use
if(record.get(tmp).equals(set.get(tmp))){
You can look at this (difference between an int and an Integer) as well as this (Integer equals vs. ==) answer
Why the first 265 test cases can pass but the last large string causes the problem?
Answer: The JVM is caching Integer values. == only works for numbers between -128 and 127

Related

Repeatedly removing a substring from a string

Problem: Remove the substring t from a string s, repeatedly and print the number of steps involved to do the same.
Example: t = ab, s = aabb. In the first step, we check if t is contained within s. Here, t is contained in the middle i.e. a(ab)b. So, we will remove it and the resultant will be ab and increment the count value by 1. We again check if t is contained within s. Now, t is equal to s i.e. (ab). So, we remove that from s and increment the count. So, since t is no more contained in s, we stop and print the count value, which is 2 in this case.
I tried to solve this using recursion
static int maxMoves(String s, String t) {
if ( null == s || "" == s || null == t || "" == t){
return 0;
}
int i = s.indexOf(t);
if(i != -1) {
return maxMoves(s.substring(0, i)+ s.substring(i+t.length(), s.length()), t) + 1;
} else {
return 0;
}
}
But I am only passing 9/14 test cases. I also tried this,
static int maxMoves(String s, String t) {
int count = 0,i;
while(true)
{
if(s.contains(t))
{
i = s.indexOf(t);
s = s.substring(0,i) + s.substring(i + t.length());
}
else break;
++count;
}
return count;
}
But that also only passed 9/14 cases.
Could anyone help me figure out which cases I am not covering?
Simply you can use String::replaceFirst with a while loop for example:
String s = "aabb";
String t = "ab";
int count = 0;
while (s.contains(t)) {
s = s.replaceFirst(Pattern.quote(t), "");
count++;
}
System.out.println(count);
Use String#replace
String s = "aabb";
String oldstr = s;
String x = "ab";
while(s.contains(x)){
s = s.replace(x, "");
}
System.out.println((oldstr.length()-s.length())/x.length());
An easy and efficient way is to accumulate the string character-by-character in a StringBuilder; if at any time its buffer ends with the string you want to replace, remove it:
StringBuilder sb = new StringBuilder();
int c = 0;
for (int i = 0; i < s.length(); ++i) {
sb.append(s.charAt(i));
int last = sb.length()-t.length();
if (last >= 0 && sb.indexOf(t, last) == last) {
sb.setLength(last);
++c;
}
}
// c is now the number of times you removed t from s.

Count a specified number

I would like to ask you a question, I want to count how many times a specified number is in a given numer (long) from the user and print it as an int.
Could you please help me with this code?
Apologize for my english.
Example:
< number specified = 4; number given = 34434544; result = 5. >
Check whether the least-significant digit is equal to the digit you are searching for; then divide by ten and check again; keep going until you reach zero.
int cnt = 0;
while (value != 0) {
if (value % 10 == digit) ++cnt;
value /= 10;
}
Where you are trying to count the occurrences of digit in the big number value.
If you're using Java 8:
long count = String.valueOf(givenNumber).chars()
.filter(c -> c == (specifiedNumber + '0'))
.count();
Make a Scanner to get input from System.in. Then, iterate through the String returned by turning it into a char[]. Then analyse each char and count original characters. Probably use a Map<Character, Integer> for this. For each element in the Map, iterate by one if it is in the Map. Query the Map for your desired character and print the result when finished.
public static void main(String[] args) {
CharacterFinder cf = new CharacterFinder();
Scanner scan = new Scanner(System.in);
String input = scan.nextLine();
Map<Character, Integer> resultsMap = cf.countChar(input);
System.out.println(resultsMap.get('g'));
}
// Note that 'null' means that it does not appear and if it is null, you ought print 0 instead.
// Also note that this method is case sensitive.
private Map<Character, Integer> countChar(String input) {
Map<Character, Integer> resultsMap = new HashMap<Character, Integer>();
for (int i = 0; i < input.length(); i++) {
Character element = input.charAt(i);
if (resultsMap.containsKey(element)) {
Integer cCount = resultsMap.get(element);
resultsMap.put(element, cCount + 1);
} else {
resultsMap.put(element, 1);
}
}
return resultsMap;
}
Well, unless you already know the char you want. In that case, analyse for that exact char.
public static void main(String[] args) {
CharacterFinder cf = new CharacterFinder();
Scanner scan = new Scanner(System.in);
String input = scan.nextLine();
// Call counting method and print
System.out.println(cf.countChar(input, '5'));
}
// Counting method
private int countChar(String input, char c) {
int x = 0;
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) == c) {
x++;
}
}
return x;
}

Searching for a digit and delete it in my int variable

I want to search a digit in my int variable and delete it.
Here is little part of the code (not finished, because i'm still on the implementation). I noticed that there are many use cases. So do you know an easier way to delete the digit?
public int getStringtoIntForEthType(int OxAB){
String myInt = Integer.toString(OxAB);
if(Integer.toString(OxAB).contains("x")){
myInt = myInt.substring(2);
}
StringBuilder myIntBuilder = new StringBuilder(myInt);
for(int a = 0; a<=myInt.length();a++){
if(a-1 < 0 && myIntBuilder.charAt(0)!=0 && myIntBuilder.charAt(a)==0){
}
}
return Integer.parseInt(myIntBuilder.toString());
}
To delete all existence of that Digit from the number here is a function :-
public int DeleteDigit(int number, int numberToDel)
{
String Num = "" + number;
Num = Num.replace(numberToDel + "", "");
if(Num.length != 0)
return Integer.parseInt(Num);
return 0;
}
this would return an integer without the digit

List collections interface in java

Please find below a function in my code:
private static List<String> formCrfLinesWithMentionClass(int begin, int end, String id,
List<String> mList, int mListPos, List<String> crf) {
List<String> crfLines = crf;
int yes = 0;
mListPosChanged = mListPos;
//--------------------------------------------------------------------------
for (int crfLinesMainIter = begin; crfLinesMainIter < end; ) {
System.out.println(crfLines.get(crfLinesMainIter));
//---------------------------------------------------------------------------
//the total number of attributes without orthographic features
//in a crfLine excluding the class attribute is 98
if (!crfLines.get(crfLinesMainIter).equals("") && crfLines.get(crfLinesMainIter).split("\\s").length == 98) {
//in mList parenthesis are represented by the symbol
//in crfLines parenthesis are represented by -LRB- or -RRB-
//we make a check to ensure the equality is preserved
if(val.equals(crfLines.get(crfLinesMainIter).split("\\s")[0])) {
yes = checkForConsecutivePresence(crfLinesMainIter, mList, mListPos, id, crfLines);
if (yes > 0) {
mListPosChanged += yes;
System.out.println("formCrfLinesWithMentionClass: "+mListPosChanged);
for (int crfLinesMentionIter = crfLinesMainIter;
crfLinesMentionIter < crfLinesMainIter + yes;
crfLinesMentionIter++) {
String valString = "";
if (crfLinesMentionIter == crfLinesMainIter) {
valString += crfLines.get(crfLinesMentionIter);
valString += " B";
crfLines.add(crfLinesMentionIter, valString);
}
else {
valString += crfLines.get(crfLinesMentionIter);
valString += " I";
crfLines.add(crfLinesMentionIter, valString);
}
}
crfLinesMainIter += yes;
}
else {
++crfLinesMainIter;
}
}
else {
++crfLinesMainIter;
}
}
else {
++crfLinesMainIter;
}
}
return crfLines;
}
The problem I face is as follows:
crfLines is a List collections interface.
When the for loop (between //-----) starts out, the crfLines.get(crfLinesMainIter) works fine. But once, it enters into the if and other processing is carried out on it, even though "crfLinesMainIter" changes the crfLines.get(crfLinesMainIter) seems to get a certain previous value. It does not retrieve the actual value at the index. Has anyone faced such a scenario? Would anyone be able to tell me why this occurs?
My actual question is, when does it occur that even though the indexes might be different a list.get() function still retrieves a value from before which was at another index?
For example:
List crfLines = new LinkedList<>();
if crfLinesMainIter = 2
crfLines.get(crfLinesMainIter) brings me a value say 20 and this value 20 satisfies the if loop condition. So then further processing happens. Now when the for loop executes the values of crfLinesMainIter changes to say 5. In this case, crfLines.get(5) should actually bring me a different value, but it still brings me the previous value 20.
(Not an answer.)
Reworked (more or less) for some modicum of readability:
private static List<String> formCrfLinesWithMentionClass(int begin, int end, String id, List<String> mList, int mListPos, List<String> crf) {
List<String> crfLines = crf;
mListPosChanged = mListPos;
int i = begin;
while (i < end) {
if (crfLines.get(i).equals("") || (crfLines.get(i).split("\\s").length != 98)) {
++i;
continue;
}
if (!val.equals(crfLines.get(i).split("\\s")[0])) {
++i;
continue;
}
int yes = checkForConsecutivePresence(i, mList, mListPos, id, crfLines);
if (yes <= 0) {
++i;
continue;
}
mListPosChanged += yes;
for (int j = i; j < i + yes; j++) {
String valString = crfLines.get(j);
valString += (j == i) ? " B" : " I";
crfLines.add(j, valString);
}
i += yes;
}
return crfLines;
}
What is mListPostChanged? I find it confusing that it's being set to the value of a parameter named mListPos--it makes me think the m prefix is meaningless.
What is val in the line containing the split?

What's the best way to check if a String represents an integer in Java?

I normally use the following idiom to check if a String can be converted to an integer.
public boolean isInteger( String input ) {
try {
Integer.parseInt( input );
return true;
}
catch( Exception e ) {
return false;
}
}
Is it just me, or does this seem a bit hackish? What's a better way?
See my answer (with benchmarks, based on the earlier answer by CodingWithSpike) to see why I've reversed my position and accepted Jonas Klemming's answer to this problem. I think this original code will be used by most people because it's quicker to implement, and more maintainable, but it's orders of magnitude slower when non-integer data is provided.
If you are not concerned with potential overflow problems this function will perform about 20-30 times faster than using Integer.parseInt().
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 < '0' || c > '9') {
return false;
}
}
return true;
}
You have it, but you should only catch NumberFormatException.
Did a quick benchmark. Exceptions aren't actually that expensivve, unless you start popping back multiple methods and the JVM has to do a lot of work to get the execution stack in place. When staying in the same method, they aren't bad performers.
public void RunTests()
{
String str = "1234567890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(str);
long endTime = System.currentTimeMillis();
System.out.print("ByException: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(str);
endTime = System.currentTimeMillis();
System.out.print("ByRegex: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(str);
endTime = System.currentTimeMillis();
System.out.print("ByJonas: ");
System.out.println(endTime - startTime);
}
private boolean IsInt_ByException(String str)
{
try
{
Integer.parseInt(str);
return true;
}
catch(NumberFormatException nfe)
{
return false;
}
}
private boolean IsInt_ByRegex(String str)
{
return str.matches("^-?\\d+$");
}
public boolean IsInt_ByJonas(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;
}
Output:
ByException: 31
ByRegex: 453 (note: re-compiling the pattern every time)
ByJonas: 16
I do agree that Jonas K's solution is the most robust too. Looks like he wins :)
org.apache.commons.lang.StringUtils.isNumeric
though Java's standard lib really misses such utility functions
I think that Apache Commons is a "must have" for every Java programmer
too bad it isn't ported to Java5 yet
Since there's possibility that people still visit here and will be biased against Regex after the benchmarks... So i'm gonna give an updated version of the benchmark, with a compiled version of the Regex. Which opposed to the previous benchmarks, this one shows Regex solution actually has consistently good performance.
Copied from Bill the Lizard and updated with compiled version:
private final Pattern pattern = Pattern.compile("^-?\\d+$");
public void runTests() {
String big_int = "1234567890";
String non_int = "1234XY7890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(big_int);
long endTime = System.currentTimeMillis();
System.out.print("ByException - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByException - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByRegex - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByRegex - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++)
IsInt_ByCompiledRegex(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByCompiledRegex - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for (int i = 0; i < 100000; i++)
IsInt_ByCompiledRegex(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByCompiledRegex - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByJonas - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByJonas - non-integer data: ");
System.out.println(endTime - startTime);
}
private boolean IsInt_ByException(String str)
{
try
{
Integer.parseInt(str);
return true;
}
catch(NumberFormatException nfe)
{
return false;
}
}
private boolean IsInt_ByRegex(String str)
{
return str.matches("^-?\\d+$");
}
private boolean IsInt_ByCompiledRegex(String str) {
return pattern.matcher(str).find();
}
public boolean IsInt_ByJonas(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;
}
Results:
ByException - integer data: 45
ByException - non-integer data: 465
ByRegex - integer data: 272
ByRegex - non-integer data: 131
ByCompiledRegex - integer data: 45
ByCompiledRegex - non-integer data: 26
ByJonas - integer data: 8
ByJonas - non-integer data: 2
It partly depend on what you mean by "can be converted to an integer".
If you mean "can be converted into an int in Java" then the answer from Jonas is a good start, but doesn't quite finish the job. It would pass 999999999999999999999999999999 for example. I would add the normal try/catch call from your own question at the end of the method.
The character-by-character checks will efficiently reject "not an integer at all" cases, leaving "it's an integer but Java can't handle it" cases to be caught by the slower exception route. You could do this bit by hand too, but it would be a lot more complicated.
Just one comment about regexp. Every example provided here is wrong!. If you want to use regexp don't forget that compiling the pattern take a lot of time. This:
str.matches("^-?\\d+$")
and also this:
Pattern.matches("-?\\d+", input);
causes compile of pattern in every method call. To used it correctly follow:
import java.util.regex.Pattern;
/**
* #author Rastislav Komara
*/
public class NaturalNumberChecker {
public static final Pattern PATTERN = Pattern.compile("^\\d+$");
boolean isNaturalNumber(CharSequence input) {
return input != null && PATTERN.matcher(input).matches();
}
}
There is guava version:
import com.google.common.primitives.Ints;
Integer intValue = Ints.tryParse(stringValue);
It will return null instead of throwing an exception if it fails to parse string.
I copied the code from rally25rs answer and added some tests for non-integer data. The results are undeniably in favor of the method posted by Jonas Klemming. The results for the Exception method that I originally posted are pretty good when you have integer data, but they're the worst when you don't, while the results for the RegEx solution (that I'll bet a lot of people use) were consistently bad. See Felipe's answer for a compiled regex example, which is much faster.
public void runTests()
{
String big_int = "1234567890";
String non_int = "1234XY7890";
long startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(big_int);
long endTime = System.currentTimeMillis();
System.out.print("ByException - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByException(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByException - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByRegex - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByRegex(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByRegex - non-integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(big_int);
endTime = System.currentTimeMillis();
System.out.print("\nByJonas - integer data: ");
System.out.println(endTime - startTime);
startTime = System.currentTimeMillis();
for(int i = 0; i < 100000; i++)
IsInt_ByJonas(non_int);
endTime = System.currentTimeMillis();
System.out.print("ByJonas - non-integer data: ");
System.out.println(endTime - startTime);
}
private boolean IsInt_ByException(String str)
{
try
{
Integer.parseInt(str);
return true;
}
catch(NumberFormatException nfe)
{
return false;
}
}
private boolean IsInt_ByRegex(String str)
{
return str.matches("^-?\\d+$");
}
public boolean IsInt_ByJonas(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;
}
Results:
ByException - integer data: 47
ByException - non-integer data: 547
ByRegex - integer data: 390
ByRegex - non-integer data: 313
ByJonas - integer data: 0
ByJonas - non-integer data: 16
This is shorter, but shorter isn't necessarily better (and it won't catch integer values which are out of range, as pointed out in danatel's comment):
input.matches("^-?\\d+$");
Personally, since the implementation is squirrelled away in a helper method and correctness trumps length, I would just go with something like what you have (minus catching the base Exception class rather than NumberFormatException).
You can use the matches method of the string class. The [0-9] represents all the values it can be, the + means it must be at least one character long, and the * means it can be zero or more characters long.
boolean isNumeric = yourString.matches("[0-9]+"); // 1 or more characters long, numbers only
boolean isNumeric = yourString.matches("[0-9]*"); // 0 or more characters long, numbers only
How about:
return Pattern.matches("-?\\d+", input);
This is a Java 8 variation of Jonas Klemming answer:
public static boolean isInteger(String str) {
return str != null && str.length() > 0 &&
IntStream.range(0, str.length()).allMatch(i -> i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')
|| Character.isDigit(str.charAt(i)));
}
Test code:
public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
Arrays.asList("1231231", "-1232312312", "+12313123131", "qwqe123123211", "2", "0000000001111", "", "123-", "++123",
"123-23", null, "+-123").forEach(s -> {
System.out.printf("%15s %s%n", s, isInteger(s));
});
}
Results of the test code:
1231231 true
-1232312312 true
+12313123131 true
qwqe123123211 false
2 true
0000000001111 true
false
123- false
++123 false
123-23 false
null false
+-123 false
You just check NumberFormatException:-
String value="123";
try
{
int s=Integer.parseInt(any_int_val);
// do something when integer values comes
}
catch(NumberFormatException nfe)
{
// do something when string values comes
}
If your String array contains pure Integers and Strings, code below should work. You only have to look at first character.
e.g. ["4","44","abc","77","bond"]
if (Character.isDigit(string.charAt(0))) {
//Do something with int
}
You can also use the Scanner class, and use hasNextInt() - and this allows you to test for other types, too, like floats, etc.
Another option:
private boolean isNumber(String s) {
boolean isNumber = true;
for (char c : s.toCharArray()) {
isNumber = isNumber && Character.isDigit(c);
}
return isNumber;
}
If you want to check if the string represents an integer that fits in an int type, I did a little modification to the jonas' answer, so that strings that represent integers bigger than Integer.MAX_VALUE or smaller than Integer.MIN_VALUE, will now return false. For example: "3147483647" will return false because 3147483647 is bigger than 2147483647, and likewise, "-2147483649" will also return false because -2147483649 is smaller than -2147483648.
public static boolean isInt(String s) {
if(s == null) {
return false;
}
s = s.trim(); //Don't get tricked by whitespaces.
int len = s.length();
if(len == 0) {
return false;
}
//The bottom limit of an int is -2147483648 which is 11 chars long.
//[note that the upper limit (2147483647) is only 10 chars long]
//Thus any string with more than 11 chars, even if represents a valid integer,
//it won't fit in an int.
if(len > 11) {
return false;
}
char c = s.charAt(0);
int i = 0;
//I don't mind the plus sign, so "+13" will return true.
if(c == '-' || c == '+') {
//A single "+" or "-" is not a valid integer.
if(len == 1) {
return false;
}
i = 1;
}
//Check if all chars are digits
for(; i < len; i++) {
c = s.charAt(i);
if(c < '0' || c > '9') {
return false;
}
}
//If we reached this point then we know for sure that the string has at
//most 11 chars and that they're all digits (the first one might be a '+'
// or '-' thought).
//Now we just need to check, for 10 and 11 chars long strings, if the numbers
//represented by the them don't surpass the limits.
c = s.charAt(0);
char l;
String limit;
if(len == 10 && c != '-' && c != '+') {
limit = "2147483647";
//Now we are going to compare each char of the string with the char in
//the limit string that has the same index, so if the string is "ABC" and
//the limit string is "DEF" then we are gonna compare A to D, B to E and so on.
//c is the current string's char and l is the corresponding limit's char
//Note that the loop only continues if c == l. Now imagine that our string
//is "2150000000", 2 == 2 (next), 1 == 1 (next), 5 > 4 as you can see,
//because 5 > 4 we can guarantee that the string will represent a bigger integer.
//Similarly, if our string was "2139999999", when we find out that 3 < 4,
//we can also guarantee that the integer represented will fit in an int.
for(i = 0; i < len; i++) {
c = s.charAt(i);
l = limit.charAt(i);
if(c > l) {
return false;
}
if(c < l) {
return true;
}
}
}
c = s.charAt(0);
if(len == 11) {
//If the first char is neither '+' nor '-' then 11 digits represent a
//bigger integer than 2147483647 (10 digits).
if(c != '+' && c != '-') {
return false;
}
limit = (c == '-') ? "-2147483648" : "+2147483647";
//Here we're applying the same logic that we applied in the previous case
//ignoring the first char.
for(i = 1; i < len; i++) {
c = s.charAt(i);
l = limit.charAt(i);
if(c > l) {
return false;
}
if(c < l) {
return true;
}
}
}
//The string passed all tests, so it must represent a number that fits
//in an int...
return true;
}
You may try apache utils
NumberUtils.isCreatable(myText)
See the javadoc here
You probably need to take the use case in account too:
If most of the time you expect numbers to be valid, then catching the exception is only causing a performance overhead when attempting to convert invalid numbers. Whereas calling some isInteger() method and then convert using Integer.parseInt() will always cause a performance overhead for valid numbers - the strings are parsed twice, once by the check and once by the conversion.
This is a modification of Jonas' code that checks if the string is within range to be cast into an integer.
public static boolean isInteger(String str) {
if (str == null) {
return false;
}
int length = str.length();
int i = 0;
// set the length and value for highest positive int or lowest negative int
int maxlength = 10;
String maxnum = String.valueOf(Integer.MAX_VALUE);
if (str.charAt(0) == '-') {
maxlength = 11;
i = 1;
maxnum = String.valueOf(Integer.MIN_VALUE);
}
// verify digit length does not exceed int range
if (length > maxlength) {
return false;
}
// verify that all characters are numbers
if (maxlength == 11 && length == 1) {
return false;
}
for (int num = i; num < length; num++) {
char c = str.charAt(num);
if (c < '0' || c > '9') {
return false;
}
}
// verify that number value is within int range
if (length == maxlength) {
for (; i < length; i++) {
if (str.charAt(i) < maxnum.charAt(i)) {
return true;
}
else if (str.charAt(i) > maxnum.charAt(i)) {
return false;
}
}
}
return true;
}
If you are using the Android API you can use:
TextUtils.isDigitsOnly(str);
I believe there's zero risk running into an exception, because as you can see below you always safely parse int to String and not the other way around.
So:
You check if every slot of character in your string matches at least
one of the characters {"0","1","2","3","4","5","6","7","8","9"}.
if(aString.substring(j, j+1).equals(String.valueOf(i)))
You sum all the times that you encountered in the slots the above
characters.
digits++;
And finally you check if the times that you encountered integers as
characters equals with the length of the given string.
if(digits == aString.length())
And in practice we have:
String aString = "1234224245";
int digits = 0;//count how many digits you encountered
for(int j=0;j<aString.length();j++){
for(int i=0;i<=9;i++){
if(aString.substring(j, j+1).equals(String.valueOf(i)))
digits++;
}
}
if(digits == aString.length()){
System.out.println("It's an integer!!");
}
else{
System.out.println("It's not an integer!!");
}
String anotherString = "1234f22a4245";
int anotherDigits = 0;//count how many digits you encountered
for(int j=0;j<anotherString.length();j++){
for(int i=0;i<=9;i++){
if(anotherString.substring(j, j+1).equals(String.valueOf(i)))
anotherDigits++;
}
}
if(anotherDigits == anotherString.length()){
System.out.println("It's an integer!!");
}
else{
System.out.println("It's not an integer!!");
}
And the results are:
It's an integer!!
It's not an integer!!
Similarly, you can validate if a String is a float or a double but in those cases you have to encounter only one . (dot) in the String and of course check if digits == (aString.length()-1)
Again, there's zero risk running into a parsing exception here, but if you plan on parsing a string that it is known that contains a number (let's say int data type) you must first check if it fits in the data type. Otherwise you must cast it.
I hope I helped
several answers here saying to try parsing to an integer and catching the NumberFormatException but you should not do this.
That way would create exception object and generates a stack trace each time you called it and it was not an integer.
A better way with Java 8 would be to use a stream:
boolean isInteger = returnValue.chars().allMatch(Character::isDigit);
What you did works, but you probably shouldn't always check that way. Throwing exceptions should be reserved for "exceptional" situations (maybe that fits in your case, though), and are very costly in terms of performance.
This would work only for positive integers.
public static boolean isInt(String str) {
if (str != null && str.length() != 0) {
for (int i = 0; i < str.length(); i++) {
if (!Character.isDigit(str.charAt(i))) return false;
}
}
return true;
}
This works for me. Simply to identify whether a String is a primitive or a number.
private boolean isPrimitive(String value){
boolean status=true;
if(value.length()<1)
return false;
for(int i = 0;i<value.length();i++){
char c=value.charAt(i);
if(Character.isDigit(c) || c=='.'){
}else{
status=false;
break;
}
}
return status;
}
To check for all int chars, you can simply use a double negative.
if (!searchString.matches("[^0-9]+$")) ...
[^0-9]+$ checks to see if there are any characters that are not integer, so the test fails if it's true. Just NOT that and you get true on success.
I have seen a lot of answers here, but most of them are able to determine whether the String is numeric, but they fail checking whether the number is in Integer range...
Therefore I purpose something like this:
public static boolean isInteger(String str) {
if (str == null || str.isEmpty()) {
return false;
}
try {
long value = Long.valueOf(str);
return value >= -2147483648 && value <= 2147483647;
} catch (Exception ex) {
return false;
}
}
When explanations are more important than performance
I noticed many discussions centering how efficient certain solutions are, but none on why an string is not an integer. Also, everyone seemed to assume that the number "2.00" is not equal to "2". Mathematically and humanly speaking, they are equal (even though computer science says that they are not, and for good reason). This is why the "Integer.parseInt" solutions above are weak (depending on your requirements).
At any rate, to make software smarter and more human-friendly, we need to create software that thinks like we do and explains why something failed. In this case:
public static boolean isIntegerFromDecimalString(String possibleInteger) {
possibleInteger = possibleInteger.trim();
try {
// Integer parsing works great for "regular" integers like 42 or 13.
int num = Integer.parseInt(possibleInteger);
System.out.println("The possibleInteger="+possibleInteger+" is a pure integer.");
return true;
} catch (NumberFormatException e) {
if (possibleInteger.equals(".")) {
System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it is only a decimal point.");
return false;
} else if (possibleInteger.startsWith(".") && possibleInteger.matches("\\.[0-9]*")) {
if (possibleInteger.matches("\\.[0]*")) {
System.out.println("The possibleInteger=" + possibleInteger + " is an integer because it starts with a decimal point and afterwards is all zeros.");
return true;
} else {
System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it starts with a decimal point and afterwards is not all zeros.");
return false;
}
} else if (possibleInteger.endsWith(".") && possibleInteger.matches("[0-9]*\\.")) {
System.out.println("The possibleInteger="+possibleInteger+" is an impure integer (ends with decimal point).");
return true;
} else if (possibleInteger.contains(".")) {
String[] partsOfPossibleInteger = possibleInteger.split("\\.");
if (partsOfPossibleInteger.length == 2) {
//System.out.println("The possibleInteger=" + possibleInteger + " is split into '" + partsOfPossibleInteger[0] + "' and '" + partsOfPossibleInteger[1] + "'.");
if (partsOfPossibleInteger[0].matches("[0-9]*")) {
if (partsOfPossibleInteger[1].matches("[0]*")) {
System.out.println("The possibleInteger="+possibleInteger+" is an impure integer (ends with all zeros after the decimal point).");
return true;
} else if (partsOfPossibleInteger[1].matches("[0-9]*")) {
System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it the numbers after the decimal point (" +
partsOfPossibleInteger[1] + ") are not all zeros.");
return false;
} else {
System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it the 'numbers' after the decimal point (" +
partsOfPossibleInteger[1] + ") are not all numeric digits.");
return false;
}
} else {
System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it the 'number' before the decimal point (" +
partsOfPossibleInteger[0] + ") is not a number.");
return false;
}
} else {
System.out.println("The possibleInteger="+possibleInteger+" is NOT an integer because it has a strange number of decimal-period separated parts (" +
partsOfPossibleInteger.length + ").");
return false;
}
} // else
System.out.println("The possibleInteger='"+possibleInteger+"' is NOT an integer, even though it has no decimal point.");
return false;
}
}
Test code:
String[] testData = {"0", "0.", "0.0", ".000", "2", "2.", "2.0", "2.0000", "3.14159", ".0001", ".", "$4.0", "3E24", "6.0221409e+23"};
int i = 0;
for (String possibleInteger : testData ) {
System.out.println("");
System.out.println(i + ". possibleInteger='" + possibleInteger +"' isIntegerFromDecimalString=" + isIntegerFromDecimalString(possibleInteger));
i++;
}

Categories