Having trouble using a HashMap with Strings and ints in Java - java

I am working on a solution to a very common Java problem involving Strings. I would like to write a method to see if a string is a permutation (anagram) of another.
My solution is this: I am writing a method that takes two Strings. I iterate through one String and put the characters that are found into a HashMap, where the key is the letter, and the value is the number of occurrences of that letter, as an int. Once I finish iterating through the first String, I iterate through the second String and decrement the values of each character found in the same HashMap.
Once a key reaches zero, I remove the key/value pair altogether from the HashMap. Once I finish iterating through the second String, I then merely check to see if the HashMap is empty. If it is, then the two Strings are permutations/anagrams of one another, otherwise the method returns false.
My method is as follows:
public boolean checkPermutation (String stringA, String stringB) {
if (stringA.length() != stringB.length()) {
return false;
}
else {
HashMap alpha = new HashMap();
for (int i = 0; i < stringA.length(); i++) {
if (!alpha.containsKey(stringA.charAt(i))) {
alpha.put(stringA.charAt(i), 0);
}
else {
Integer value = (Integer) alpha.get(stringA.charAt(i));
int newValue = value.intValue();
alpha.put(stringA.charAt(i), newValue++);
}
}
for (int j = 0; j < stringB.length(); j++) {
if (alpha.containsKey(stringB.charAt(j))) {
Integer value = (Integer) alpha.get(stringA.charAt(j));
int newValue = value.intValue();//null pointer exception here
if (newValue > 1) {
alpha.put(stringB.charAt(j), newValue--);
}
else {
alpha.remove(stringB.charAt(j));
}
}
}
if (alpha.isEmpty())
return true;
else
return false;
}
}
My problem is that my solution is case-sensitive (i.e. If I enter "Hello", and "oellH", I get a null pointer exception). I would like to make this solution case-insensitive, and figure out why I am getting a Null-Pointer Exception. Can anyone see what I am doing wrong?
As a minor follow up question, is such a solution of type O(n) despite there being two for-loops?

Integer value = (Integer) alpha.get(stringA.charAt(j));
Try changing stringA to stringB.
Integer value = (Integer) alpha.get(stringB.charAt(j));
Because if you give different String which dont have same characters in it the value will be null and it will through NPE.
Change both string to lowercase or uppercase.
stringA= stringA.toLowercase();
stringB= stringB.toLowercase();

The null pointer exception is thrown because you are checking for char of stringB in hashmap and then extracting value of stringA there may chances when that particular value is removed from the hashmap at that time the null pointer error is thrown.
If you carefully debug your code in
if (alpha.containsKey(stringB.charAt(j))) {
Integer value = (Integer) alpha.get(stringA.charAt(j));
///Your code
}
Change it to
if (alpha.containsKey(stringB.charAt(j))) {
Integer value = (Integer) alpha.get(stringB.charAt(j));
///Your code
}
For your other question to make it case insensitive make both the string in lower case o upper case before beginning the operation
stringA = stringA.toLowerCase();
stringB = stringB.toLowerCase();

Related

How to return nothing when count is equal to zero?

I want the function countChar to only return a value if the count is greater than zero, otherwise i want it to just return nothing.
I understand that the method cannot return null as null can't be an Int. Is there another way to effectively return a "null" value?
public static int countChar(String str, char ch){
int count = 0;
for (int i=0;i<str.length();i++) {
if (str.charAt(i)==ch)
count++;
}
if (count>0) {
return count;
}else{
return null;
}
}
error: incompatible types: cannot be converted to int
return null;
^
I would like it to return absolutely nothing instead of zero.
Use Integer instead of int, everything else remains unchanged:
public static Integer countChar(String str, char ch){...}
But then the method naming wouldn't make sense- countChars counts the number of times a char occurs in a string. If a particular char doesn't occur then 0 is a perfectly reasonable response. Null isn't really a reasonable response - if you want null then have the method that calls countChars get a 0 back and proceed as if it were null:
int result = countChars("Hello world", 'z');
if(result == 0)
someMethod(null);
else
someMethod(result.ToString());
Even throwing an exception would be better than returning null because it at least tells the developer who is using your code, what is wrong and gives some clue on how to fix it. Asking code to do something that shouldn't really return a blank response, and getting a blank response can be incredibly frustrating to work with
You can change it in two ways.
By changing the comparing logic as given. It won't return anything if it is zero.
if (count > 0) {
return count;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~
OR
2. You can return null but change the return type of method from primitive to nonprimitive.
~~~~~~~~~~~~~~~~~~~~
public static Integer countChar(String str, char ch){
---
---
if (count>0) {
return count;
}
return null;
}
~~~~~~~~~~~~~~~~~~~

Converting a String to int. Set the int to 0 if String is null

I have a function which saves Android data in sqlite but I have to convert the String data to an Integer.
Whenever the String is null i would like to save as 0
The following is my code which fails whenever the value is null
int block_id = Integer.parseInt(jsonarray.getJSONObject(i).getString("block_id"));
The block_id above is converted to an Integer.
This is what i have decided to do but still it fails to convert the string value to 0 whenever its null.
int block_id = Converttoint(jsonarray.getJSONObject(i).getString("block_id"));
Then the function convertToInt
public static Integer convertToInt(String str) {
int n=0;
if(str != null) {
n = Integer.parseInt(str);
}
return n;
}
How should I change it, to make it work?
Simply use the built-in method JSONObject#getInt(String), it will automatically convert the value to an int by calling behind the scene Integer.parseInt(String) if it is a String or by calling Number#intValue() if it is a Number. To avoid an exception when your key is not available, simply check first if your JSONObject instance has your key using JSONObject#has(String), this is enough to be safe because a key cannot have a null value, either it exists with a non null value or it doesn't exist.
JSONObject jObj = jsonarray.getJSONObject(i);
int block_id = jObj.has("block_id") ? jObj.getInt("block_id") : 0;
Instead of writing your own function use the inbuild construction of try-catch. Your problem is, that jsonarray or jsonarray.getJSONObject(i) or the value itself is a null and you call a method on null reference. Try the following:
int block_id = 0; //this set's the block_id to 0 as a default.
try {
block_id = Integer.parseInt(jsonarray.getJSONObject(i).getString("block_id")); //this will set block_id to the String value, but if it's not convertable, will leave it 0.
} catch (Exception e) {};
In Java Exceptions are used for marking unexpected situations. For example parsing non-numeric String to a number (NumberFormatException) or calling a method on a null reference (NullPointerException). You can catch them in many ways.
try{
//some code
} catch (NumberFormatException e1) {
e.printStackTrace() //very important - handles the Exception but prints the information!
} catch (NullPointerException e2) {
e.printStackTrace();
}
or using the fact, that they all extend Exception:
try {
//somecode
} catch (Exception e) {
e.printStackTrace;
};
or since Java 7:
try {
//somecode
} catch (NullPointerException | NumberFormatException e) {
e.printStackTrace;
};
Note
As I believe, that you'll read the answer carefully, please have in mind, that on StackOverflow we require the Minimal, Complete, and Verifiable example which include the StackTrace of your exception. In your case it probably starts with the following:
Exception in thread "main" java.lang.NullPointerException
Then, debugging is much easier. Without it, it's just guessing.
Edit: According to the accepted answer
The accepted answer is good and will work as long, as the value stored with key: block_id will be numeric. In case it's not numeric, your application will crash.
Instead of:
JSONObject jObj = jsonarray.getJSONObject(i);
int block_id = jObj.has("block_id") ? jObj.getInt("block_id") : 0;
One should use:
int block_id;
try{
JSONObject jObj = jsonarray.getJSONObject(i);
block_id = jObj.has("block_id") ? jObj.getInt("block_id") : 0;
} catch (JSONException | NullPointerException e) {
e.printStackTrace();
}
There is one more way to do this apart from the methods given in rest of the answers.
String blockId=jsonarray.getJSONObject(i).getString("block_id");
int block_id = blockId==null ? 0 : Integer.parseInt(blockId);
You can check for NumberFormatException. Integer.parseInt() will throw NumberFormatException for cases:
String is null
String is empty ("")
String cannot be converted to int for any other reason (say String is "aff" or "1.25")
Basically, it will handle all possible non-integer cases.
Code Example:
private static int convertStringToInt(String str){
int x = 0;
try{
x = Integer.parseInt(str);
}catch(NumberFormatException ex){
//TODO: LOG or HANDLE
}
return x;
}
You can use following method,
String id = jsonarray.getJSONObject(i).getString("block_id")
int blockId = getBlockId(id);
#NonNull
private Integer getBlockId(String id) {
Integer blockId= 0;
try {
blockId= Integer.parseInt(id);
} catch (NumberFormatException e) {
e.printStackTrace();
}
return blockId;
}
String toBeParsedStr="1234";
int parsedInt=toBeParsedStr!=null&&toBeParsedStr.matches("[0-9]+")?Integer.parseInt(toBeParsedStr):0;
Try this
int block_id = (jsonarray.getJSONObject(i).has(block_id)) ? jsonarray.getJSONObject(i).getInt("block_id") : 0;
you can use Integer.getInteger("30").intValue()
int block_id_0 = jObj.optInt("block_id");
The ternary condition and multiple code can simply be replaced with optInt function in a single line, which simply
1.) return the default value or 0 if no value is there (depends upon the variant you are using).
2.) Try to convert the value, if the value is available as string
3.) Simply No null or NumberFormat exceptions at all in case of missing key or value
Android docs
int optInt (String name)
int optInt (String name, int fallback)
Maven-Central
int optInt(String key, int defaultValue)
To get a specified default value if no value available
Get an optional int value associated with a key, or the default if
there is no such key or if the value is not a number. If the value is
a string, an attempt will be made to evaluate it as a number.
jObj.optInt("block_id",defaultvalue);
or
To get a default value as 0 if no value available
Get an optional int value associated with a key, or zero if there is
no such key or if the value is not a number. If the value is a string,
an attempt will be made to evaluate it as a number.
jObj.optInt("block_id");
e.g
int block_id = jObj.optInt("block_id",5);
block_id will be 5 if no key/value available
int block_id_0 = jObj.optInt("block_id");
block_id_0 will be 0 if no key/value available
There are other variant of this function available for other datatypes as well , try the docs link above.
String str = "...";
// suppose str becomes null after some operation(s).
int number = 0;
try
{
if(str != null)
number = Integer.parseInt(str);
}
catch (NumberFormatException e)
{
number = 0;
}
Notice.. you could also write it like that
public static Integer convertToInt(String str) {
int n=0;
if(str != null && str.length()>0) {
n = Integer.parseInt(str);
}
return n;
}
but the try/catch method is way more effective and simple and will not cause a system exit if a letter get inside the String (just worth mentioning)
also, it is important to notice that writing the same equation like that:
if(str != null & str.length()>0) {}
or like that:
if(str.length()>0 && str != null) {}
can cause the operation to fail because it will try to count the String even if it is null
Hope I responded to all your questions
Your function should work fine only when the param is an empty string instead of null
If the param is empty string ,Integer.parseInt would throw a NumberFormatException instead of return 0

ArrayOutOfBounds error when i run a for-each-loop in java

I'm writing a code that looks through a given array list named values and returns True if found i've gotten it to work for a for-loop and a while-loop but can't figure out how to get the for-each loop to work. Here is what i have that'd giving me the error.
EDIT: the error says "java.lang.IndexOutOfBoundsException: Index:642327, Size 30590 (in java.util.ArrayList)
public String twoforEachFoundIt(ArrayList<Integer> values, int number){
for(int i:values) {
if (values.get(i)== number){
return "True";
}
}
return null;
}
When you're iterating over the list, you're putting the contents of the list into i. Then you're using that i as an index into the list.
You can just compare i directly:
if (i == number)
return "True";
As a note, you may want to change your function to return a boolean rather than a String...
The variable 'i' has the value of the element and not the index. Correct way is :
if ( i== number)
return "true"
Since foreach is iterating over the elements of the ArrayList values, you must compare number with the actual element:
for (int i : values) {
if (i == number){
return "True";
}
}
If you want to use indexes, use a simple for:
for(int i = 0; i < values.size(); i++) {
if (values.get(i) == number){
return "True";
}
}
The foraech give you the content of the array values and not the index. You can simply compare:
if (i == number){
return "True";
}

Searching array

I'm trying to figure out how to create a method to find a string inside an array and print that string out along with its index. I think the method signature is correct but I can't figure out how to return the string value in the method.
String name = search(array,"Dog"); //the method implementation in main
System.out.println(name);
.
public static int search(String[] array, String key)
{
for (int i= 0; i< array.length; i++)
{
if ( array[i] == key )
return i;
}
return ("Name cannot be found in array);
}
You can't return a String from a method that is declared to return int. The most common ways to indicate failure are to return an out-of-range value:
return -1;
Or to throw an exception:
throw new NameNotFoundException("Name cannot be found in array");
Also, this line won't work:
if ( array[i] == key )
Strings need to be compared with equals(), not ==. The == operator checks that the strings are the same objects, not that their contents are identical.
if (key == null && array[i] == null ||
key != null && key.equals(array[i]))
And make sure that you don't call .equals() on a null reference. The above code checks for this possibility.
Why do you want to return the String? Whoever calls this method already knows what the String is, because they had to provide it in the first place. (Otherwise how would know what you were looking for :P)
also you should be doing array[i].equals(key).
== is for object equality.
.equals() is for value equality.
If you want to return a String, then...your return type should be String, not int.
Also, you shouldn't use == with Strings, or with most objects, use array[i].equals(key) instead.
The biggest question is why implement search when java has already implemented it for you?
String[] array;
String val = "Dog";
if( Arrays.asList(array).contains(val) ){
System.out.println("your string is found");
} else {
System.out.println("your string is found");
}
Or better yet true to you implementation
String[] array;
String val = "Dog";
String name = ( Arrays.asList(array).contains(val) ) ? val : "Name cannot be found in array";
it should be noted that Arrays.asList DOES NOT COPY the array merely wraps it in a List structure so that it can be treated as a enumerable. The performance of this method is roughly the same as the one your provided.
You allready have String value that you are searching. Why you need to return that ?
Just return index
int index = search(array,"Dog");
First fix your comparison to use the equals method as:
if (array[i].equals(key))
Also change last return statement as:
return -1; //string not found
Then simply do this (use array[searchIndex] to get the string):
int searchIndex = search(array,"Dog");
if(i >= 0){
System.out.println("String="+array[searchIndex] + ", Array Index="+searchIndex);
}else{
System.out.println("String not found");
}
you can try this one .............
import java.util.*;
public class xyz {
public static void main(String [] args){
String [] sa = {"abc","def","ghi"};
Arrays.asList(sa);
Arrays.sort(sa);
for(String s : sa){
System.out.println(s);
}
}
}

Java list : get next or previous element from an identifier

I want to navigate into a list by identifier.
1- I manage/create a list.
2- I create function to get next item of a identifier element from my list
Can you help me to fix this code?
Prepare the list
List<String> myList = new ArrayList<String>();
myList.add("1");
myList.add("2");
myList.add("3");
myList.add("4");
myList.add("5");
public String function getNext(String uid) {
if (myList.indexOf(uid).hasNext()) {
return myList.indexOf(uid).nextElement();
}
return "";
}
public String function getPrevious(String uid) {
return myList.indexOf(uid).hasPrevious() ? myList.indexOf(uid).previousElement() : "";
}
You could use an index to lookup your String which is faster and simpler however to implement the functions as you have them.
public String getNext(String uid) {
int idx = myList.indexOf(uid);
if (idx < 0 || idx+1 == myList.size()) return "";
return myList.get(idx + 1);
}
public String getPrevious(String uid) {
int idx = myList.indexOf(uid);
if (idx <= 0) return "";
return myList.get(idx - 1);
}
Using a List.get(i) is O(1) which makes keeping the index the fastest option. List.indexOf(String) is O(n). Using a NavigatbleSet might appear attractive as it is O(log n), however the cost of creating an object is so high that the collection has to be fairly large before you would see a benefit. (In which case you would use the first option)
If your elements are not repeated, what you need is a NavigableSet:
http://download.oracle.com/javase/6/docs/api/java/util/NavigableSet.html
The methods higher and lower are what you are looking for.
Lists don't have a nextElement() method. indexOf returns the integer index of the item. You could simply add (or subtract) one to get the next (or previous) item:
public String function getNext(String uid) {
var index = myList.indexOf(uid);
if (index > -1) {
try {
return myList.get(i+1);
} catch ( IndexOutOfBoundsException e) {
// Ignore
}
}
return ""; // consider returning `null`. It's usually a better choice.
}
However looking up an object with indexOf on ArrayList is a very slow process, because it has to check every single entry. There are better ways to this, but that depends on what you are actually trying to achieve.

Categories