Extracting from delimited string - java

Would appreciate comment on whether this is the best/recommended way to parse a pipe-delimited string for particular keys.
In a low-latency system which runs this operation for every request - inefficiency is expensive.
public String extractFields(String key,String comment){
if(comment!=null){
for(String test:comment.split("\\|")){
if(test.contains(key)){
return test.substring(test.indexOf(key)+key.length()).trim();
}
}
}
return null;
}

Hmm, the split and search seems a bit pointless to me.
Why not:
indexOf() of the key to get its location, test if this is valid
If valid, from that location, do indexOf() to the next |
Return a substring of the above region.

Based on Nim's answer, here is an implementation of the faster way to do it:
public String extractField(String key, String comment) {
if (key == null || comment == null)
return null;
int i = comment.indexOf(key);
if (i < 0) // Does not contain the key
return null;
String result = comment.substring(i + 1);
i = result.indexOf('|');
if (i >= 0)
result = result.substring(0, i);
return result;
}

Related

All combinations of alphanumeric string, better way?

The input to the "alphaNumeric" function is a String which consists of alphanumeric characters that are all lower case, for example "hello123hello". I want to be able to check all upper/lower case letter combinations for this string through a check( ) function. (Eg. HeLlO123hELlo is one of the combinations to be checked). I have written code in Java to do this where I store the matching String into an ArrayList, but would like to know if there a better way to do this without the ArrayList. Also, am I correct in saying the worst case runtime of this is O(2^n)? Note: Check is a function that returns either true or false, depending on whether the correct String is passed to the function.
public static String alphaNumeric(String input) {
ArrayList<String> list = new ArrayList<String>();
alphaHelper(input, "", list);
return list.get(0);
}
private static void alphaHelper(String in, String current, ArrayList<String> list) {
if (in.length() == 0) {
if (check(current)) {
list.add(current);
}
} else if (Character.isLetter(in.charAt(0))) {
alphaHelper(in.substring(1),current+in.substring(0,1).toLowerCase(),list);
alphaHelper(in.substring(1),current+in.substring(0,1).toUpperCase(),list);
} else if (Character.isDigit(in.charAt(0))) {
alphaHelper(in.substring(1),current+in.substring(0,1),list);
} else {
return;
}
}
If you just want to remove the ArrayList without changing your basic algorithm, you can do this:
public static String alphaNumeric(String input) {
return alphaHelper(input, "");
}
private static String alphaHelper(String in, String current) {
String result = null;
if (check(current)) {
result = current;
} else if (Character.isLetter(in.charAt(0))) {
result = alphaHelper(in.substring(1),current+in.substring(0,1).toLowerCase());
if (result == null) result = alphaHelper(in.substring(1),current+in.substring(0,1).toUpperCase());
} else if (Character.isDigit(in.charAt(0))) {
result = alphaHelper(in.substring(1),current+in.substring(0,1));
}
return result;
}
Yes it is O(2^n), and I can't see offhand how you would improve on that if you can't get the original string directly.
If you don't need to check substrings (i.e. you only care about case variations of the entire string) you could improve the algorithm by not testing the substrings, but it would still be O(2^n).
You could temporarily set both the check and input to lowercase and compare them then.
public static boolean alphaNumeric(String input, String check) {
return input.toLowerCase().equals(check.toLowerCase());
}
-Sean

collection sort multi items

Am currently trying to sort my object by lastname first then first name then date of birth then ssn. But logically I can only come up with is the lastname then the firstname
any tips?
public int compareTo(Doctor o)
{
int result = this.lastName.compareTo(o.lastName());
return result == 0 ?this.firstName.compareTo(((Doctor) o).firstName()):result;
}
Nested if would be better choice to implement this.
public int compareTo(Doctor o){
int result = this.lastName.compareTo(o.lastName());
if(result==0){
result = this.firstName.compareTo(o.firstName());
if(result==0){
result = this.dob.compareTo(o.dob());
if(result==0){
....
}
}
}
return result;
}
You can use the following:
public int compareTo(Doctor o)
{
int result = this.lastName.compareTo(o.lastName());
if (result != 0)
return result;
result = this.firstName.compareTo(o.firstName());
if (result != 0)
return result;
result = this.birthDate.compareTo(o.birthDate());
if (result != 0)
return result;
return this.ssn.compareTo(o.ssn());
}
First sort on lastname. If the sort value is 0, sort on firstname. If that result is 0, sort for date of birth, and so on. You'll have multiple return statements, sure, but it's a lot more readable.
As you probably know, a result value of 0 means the two values are equal. In your use case, this should result in an additional sort instead of simply returning the values.
Edit: other answers below have provided exact implementation for this.
As you may have realized, this is a kind of the "chain of responsibility". So i would suggest you the pattern for this case. Chain-of-responsibility Pattern
It will save you from writing too many if()...s

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.

In java, how to append string ignoring duplicates

I have string say "ABC,D" , now I wish to write a method append(initialStr, currStr ) which appends currStr to initailStr only if currstr is not already present in initialStr. I tried a method which splits with comma, but since my string contains comma so that method doesn't works for me. Any help will be greatly appreciated.
String appendIfNotPresent(String initial, String curr)
{
if (initial.contains(curr))
return initial;
else
return initial + curr;
}
I'd write it like so, to make it work for null values:
String appendIfNotContained(String initial, String curr) {
if (initial == null) {
return curr;
} else if (curr == null) {
return initial;
} else {
return initial.contains(curr) ? initial : initial + curr;
}
}
You can use indexOf to search for currStr. If the indexOf method returns -1, then there is no match. Any other number will be the starting location of the substring.
if(initialStr.indexOf(currStr) == -1) {
initialStr += currStr;
}
Also, if case doesn't matter you can add toLowerCase() or toUpperCase() to the above code sample:
if(initialStr.toLowerCase().indexOf(currStr.toLowerCase()) == -1) {
initialStr += currStr;
}
If you have a lot of string operations to perform, I recommend looking at the StringUtils class from the Apache Commons Lang library. It provides a lot of useful methods. Here is a link to the API: http://commons.apache.org/lang/api-release/org/apache/commons/lang/StringUtils.html
One option is to use indexOf() to determine if one string is contained in another.
int i = initialStr.indexOf(currStr)
if(i != -1){
//go ahead and concatenate
}

Categories