Searching for a string within an array - java

Below I am trying to create a method which searches through an array for a certain string and returns the position of it, if not there then -1 should be the number returned. Below I search for a word using the method and it returns -1 even though the word is within the array. Why is this?
String answer = "";
System.out.println("Enter word to search within array");
answer = in.next();
public static int search(String[] theWords, String answer) {
int a = -1;
for(int i = 0; i < theWords.length; i++) {
if (answer.equals(theWords[i])){
a = i;
break;
}
}
return a;
}

I can't see anything wrong with the code, but I would recommend eliminating the local variable that holds the return value:
public static int Search(String[] thewords, String answer) {
for (int i = 0; i < thewords.length; i++) {
if (answer.equals(thewords[i])){
return i;
}
}
return -1;
}
With this simplified logic, there's little or no chance of there being a bug in this code.
I assume this is course work, and you are not allowed to use library methods. If you were allowed, your method could be a single line:
return Arrays.asList(theWords).indexOf(answer);

You can optionally make a copy of the array since sorting might be unwanted for consumers of the method
public static int Search(String[] thewords, String answer) {
if(thewords == null) {
throw new NullPointerException();
}
String[] copy = new String[thewords.length];
System.arraycopy(thewords,0,copy,0,copy.length);
Arrays.sort(thewords);
return Arrays.binarySearch(thewords, answer);
}
Note: It returns -pos and not -1
If you need -1:
public static int Search(String[] thewords, String answer) {
if(thewords == null) {
throw new NullPointerException();
}
String[] copy = new String[thewords.length];
System.arraycopy(thewords,0,copy,0,copy.length);
Arrays.sort(thewords);
int idx = Arrays.binarySearch(thewords, answer);
return idx < 0? -1:idx;
}
Concerning your code: I believe the problem would be related to casing or spacing:
Replace with something like: if (answer.equalsIgnoreCase(theWords[i].trim())){
For large arrays go with binary search.

Related

How to work around a NullPointerException in Java?

So I have a text file that contains a bunch of strings that I import into the program and what my program does is look for the first index of the first duplicate string:
static final int NOT_FOUND = -1;
dupeIndex = indexOfFirstDupe( wordList, wordCount );
if ( dupeIndex == NOT_FOUND )
System.out.format("No duplicate values found in wordList\n");
else
System.out.format("First duplicate value in wordList found at index %d\n",dupeIndex);
and the method I use to find the first index of the duplicate is as follows:
static int indexOfFirstDupe( String[] arr, int count )
{
Arrays.sort(arr);
int size = arr.length;
int index = NOT_FOUND;
for (int x = 0; x < size; x++) {
for (int y = x + 1; y < size; y++) {
if (arr[x].equals(arr[y])) {
index = x;
break;
}
}
}
return index;
The problem is that I get this error:
It's a NullPointerException and from my understanding it means that there's basically a null value(s) in my array of strings(?). Is there any simple solution to this that I am missing? Possibly rewording my method?
The error is caused by Array.sort(arr);
According to Java doc (https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#sort-java.lang.Object%3aA-):
Sorts the specified array of objects into ascending order, according to the natural ordering of its elements. All elements in the array must implement the Comparable interface.
It is very likely that the exception was thrown when the sort tries to call the compareTo method on the null objects of the String array.
So one simple direct solution is to make sure no null objects in your String array...
There is a better way to do what you want to do.
This is complexity O(n) vs yours is O(n^2) + failing sort.
public int indexOfFirstDup(String[] arr) {
Set<String> valuesFound = new HashSet<>();
for (int i=0;i<arr.length; i++) {
String s = arr[i];
// ignore nulls
if (s == null) { continue; }
if (valuesFound.contains(s)) {
// here we identified a duplication and we can leave
return i;
} else {
valuesFound.add(s);
}
}
// no dups
return -1;
}
NOTE the code has not been compiled nor tested - its just an idea!
Assuming that you are correct in your diagnosis
... it means that there's basically a null value(s) in my array of strings ...
... I can think of two workarounds.
Get rid of the null references in the array. Remove them entirely, or replace them with (say) "" or "null" or something else harmless.
There is an overload of the Arrays.sort method that takes a second argument: a Comparator. So what you could do is to implement a Comparator that can handle null without throwing an NPE. (For example, it could treat null as smaller than all non-null strings.)
Here's an example comparator that deals with null:
public class NullSafeStringComparator implements Comparator<String> {
public int compare(String s1, String s2) {
if (s1 == s2) {
return 0;
} else if (s1 == null) {
return -1;
} else if (s2 == null) {
return 1;
} else {
return s1.compareTo(s2);
}
}
}
Alternatively, for Java 8 and later you can build one as follows:
Comparator.nullsFirst(Comparator.naturalOrder())

Java - breaking out of a incursion method and returning the value

Good morning all,
Today is my first time trying to make a recursion method. Just when I thought it would work I got the error; missing return statement. This confuses me because it literally has a return value ( the total string from the Stringbuilder ) after n < 1
This is what I got:
import java.util.Scanner;
public class P5_4MethodRepeatString {
public void main(String[] args){
Scanner sc = new Scanner(System.in);
System.out.println("Enter a string followed by the times you want
it repeated:");
String input = sc.nextLine();
int count = sc.nextInt();
String total = repeat(input, count);
System.out.println(total);
}
public static String repeat(String str, int n) {
StringBuilder full = new StringBuilder();
if(n < 1) {return full.toString();}
repeat(str, n - 1);
for(int i = 0; i < n; i++){
full.append(str);
}
}
}
if(n < 1) {return full.toString();} but if n >= 1 you don't return anything. It should be return repeat(str, n - 1); but then you need to move the for... part
The immediate cause of your problem is that not all conditional flows in your repeat() method have a return value. But I am not sure if even making that change would result in working code. Consider the following refactor:
public void repeat(StringBuilder result, String str, int n) {
if (n == 0) return;
result.append(str);
repeat(result, str, n - 1);
return;
}
Here we are passing in a StringBuilder object which we want to contain our repeated string results. We also pass the string to be repeated, and the number of remaining turns. The base case occurs where there are no more turns, in which case we simply return from the recursive method. Otherwise, we add one copy of the string and make a recursive call.
Your original recursive attempt had the following for loop:
for (int i=0; i < n; i++) {
full.append(str);
}
This does not look recursive, and looping to repeatedly add the string defeats the point of doing recursion (though I would probably use a loop in real life if I had to do this).

Rewriting the whole String Class methods

My professor have given me a challenging homework, where the idea is to rewrite all the methods in the String classes without using String, StringBuilder, and Wrapper classes. This is for Intro to Java class. I already have some methods done but having a hard time with some other ones. This is for the main class only with no creation of any string inside.
What I have: a "data" as a char[] data for my "MyOwnString" object.
CompareTo method:
public int compareTo(MyOwnString rhs){
if (this.data == rhs.data){
return 0;
} else if (this.data > rhs.data){
return 1;
}
else {
return -1;
}
}
This one shows an error. My guess is that the rhs needs to be declare before being able to compare to any string being assigned to a MyOwnString object.
Since there is a compareTo method and a compareToIgnoreCase, then I would have to add a line to ignore the comparsion?
Update:
This is the code I went with for the compareTo method by creating own method using length of the array.
public int compareTo(MyOwnString cts){
int word1 = data.length;
int word2 = cts.length();
int result = 0;
for (int i=0; i<word1; i++){
for (int j=0;j<word2; j++){
if(word1 == word2){
result = 0;
}
else if (word1 > word2){
result = 1;
}
else {
result = -1;
}
}
}
return result;
}
Since you are not allowed to use String.compareTo()
and since java doesn't support > for your custom objects or char[] for that matter (e.g doesn't support operator overloading) you have to do it programmatically.
In other words you have the two char arrays and you have to loop through all the characters. You compare the first two characters from each of the char arrays (there you can use > or <) if they are == you compare the second two characters and so on.. till you find two characters that break the tie - you can then break your for loop and return the result as -1, 1. If they are tied on every character you return 0.
If you want to implement equals you could just call compareTo and optimize it a bit by checking the lengths of the strings. If they are different then of course the strings are not equal
Update: I am not sure if you ran your code above - try to compile your code and run it before you move forward. I believe it won't even compile.
Here is, I believe, a correct unchecked version. I could have mixed the -1 and 1s as always..
public int compareTo(MyOwnString cts){
int word1Length = ((MyOwnString)this).data.length;
int word2Length = cts.data.length;
for (int i=0; i < Math.min(word1Length,word2Length); i++){
if(this.data[i] == cts.data[i]){
continue;
}
else if (this.data[i] > cts.cts[i]){
return -1;
}
else if (this.data[i] < cts.cts[i]) {
return 1;
}
}
if (word1Length == word2Length){
return 0;
}
else if(word1Length < word2Length){
return 1;
}
else {
return -1;
}
}
public boolean equals(MyOwnString cts){
int word1Length = ((MyOwnString)this).data.length;
int word2Length = cts.data.length;
if (word1Length != word2Length){
return false;
}
else { // if they are equal
int comparison = this.compareTo(cts);
if (comparison==0){
return true;
}
else {
return false;
}
}
}
You can't compare char[] objects with the > operator, since it's not defined on them. You'll have to iterate over the char[] arrays and compare the characters yourself.
BTW, it's very easy to cheat in this assignment, since the code of the String class is available online.

Detail formatter error: java.util.Arrays cannot be resolved to a type

I have developed a BlackBerry application where in I am reading in a HEX String values. The values returned are as follows:
String result = response.toString();
where result is:
["AC36C71DF3CB315A35BFE49A17F483B6","CF5B717ACC460E3C4545BE709E9BCB83","E1EE334738CA4FA14620639DD6750DC3","DD40E2822539C2184B652D1FC3D2B4E6","6AF4B1EAC8D8210D64A944BFD487B9F2"]
These are passed into the following split method to separate the values. The method is as follows:
private static String[] split(String original, String separator) {
Vector nodes = new Vector();
int index = original.indexOf(separator);
while (index >= 0) {
nodes.addElement(original.substring(0, index));
original = original.substring(index + separator.length());
index = original.indexOf(separator);
}
nodes.addElement(original);
String[] result = new String[nodes.size()];
if (nodes.size() > 0) {
for (int loop = 0; loop < nodes.size(); loop++) {
result[loop] = (String) nodes.elementAt(loop);
System.out.println(result[loop]);
}
}
return result;
}
The above array is passed is as the String original in the method. This part is working fine. However, when a single value is passed in as String original, i.e. ["6AF4B1EAC8D8210D64A944BFD487B9F2"], I get an error :
Detail formatter error:java.util.Arrays cannot be resolved to a type.
Please help !!! The values posted above are exact values as read including the parenthesis [] and quotations ""
The Blackberry libraries are based on Java ME and not Java SE. In Java ME some classes have been removed to reduce the runtime footprint such as the Arrays class.
Take a look at the Blackberry JDE java.util package, see there is no Arrays class. So in your code you cannot use methods coming from the Arrays class, you must found a workaround or implement the feature yourself.
Try this split method -
public static String[] split(String strString, String strDelimiter) {
String[] strArray;
int iOccurrences = 0;
int iIndexOfInnerString = 0;
int iIndexOfDelimiter = 0;
int iCounter = 0;
//Check for null input strings.
if (strString == null) {
throw new IllegalArgumentException("Input string cannot be null.");
}
//Check for null or empty delimiter strings.
if (strDelimiter.length() <= 0 || strDelimiter == null) {
throw new IllegalArgumentException("Delimeter cannot be null or empty.");
}
if (strString.startsWith(strDelimiter)) {
strString = strString.substring(strDelimiter.length());
}
if (!strString.endsWith(strDelimiter)) {
strString += strDelimiter;
}
while((iIndexOfDelimiter = strString.indexOf(strDelimiter,
iIndexOfInnerString)) != -1) {
iOccurrences += 1;
iIndexOfInnerString = iIndexOfDelimiter +
strDelimiter.length();
}
strArray = new String[iOccurrences];
iIndexOfInnerString = 0;
iIndexOfDelimiter = 0;
while((iIndexOfDelimiter = strString.indexOf(strDelimiter,
iIndexOfInnerString)) != -1) {
strArray[iCounter] = strString.substring(iIndexOfInnerString,iIndexOfDelimiter);
iIndexOfInnerString = iIndexOfDelimiter +
strDelimiter.length();
iCounter += 1;
}
return strArray;
}

java creating a class method that searches an array for word length

so i've already made a class method that searches for a specific word, but (like most times i find myself on here!) i've had a brain malfunction and can't figure out how to modify it to do what i need. here's what i've got so far:
private static int findFourLetterWord(String[] strings, String key) {
for (int i = 0; i < strings.length; i++)
if (strings[i].equals(key))
return i;
return -1;
}
so this searches an array for 'key' and returns with it's position if it is found. what i'm trying to get it to do is search an array of strings for the first 4 letter word it encounters and return with that word. i would change the first return to be System.out.println(strings[i]); i believe, but i'm not sure how to make it search for the first 4 letter word it finds. tried using a bunch of convoluted substrings but that didn't work. any advice or guidance would be great. thank you in advance.
Your current method is close; you just need to change the condition in the for-loop to check for a length of 4 using String#length() rather than equality to a key argument.
private static String findFourLetterWord(String[] strings) {
for (String str : strings) {
if (str.length() == 4) {
return str;
}
}
return null;
}
Never forget to consult the JavaDocs when you find yourself unsure of what methods are available for your convenience.
Am I understanding your question right?
private static String findFourLetterWord(String[] strings) {
for (int i = 0; i < strings.length; i++)
if (strings[i].length()==4)
return strings[i];
return null;
}
Use substring function to get the first 4 character of the key and string as below:
private static int FindFourLetterWord(String[] strings, String key) {
//Assuming key length is 4 or more
String keyWithFourChars = key.substring(0,4);
for (int i = 0; i < strings.length; i++){
if(strings[i].length() > 3){
if (strings[i].substring(0,4).eqauls(keyWithFourChars)){
return i;
}
}
}
return -1;
}
If you want to just look for 4 chars string, then simply check the length as below:
In this case, you don't need to pass key as parameter.
private static int FindFourLetterWord(String[] strings) {
for (int i = 0; i < strings.length; i++){
if(strings[i].length() == 4){
return i;
}
}
return -1;
}

Categories