# Efficient way to copy unordered String into ordered String

I'm doing this in Hadoop Java where I'm reading a String. The string is huge that has been tokenized and put in an array. It has key-value pairs but they are not in any order. I want this order to be rigid so I can load that as a table. So in SQL, if I select a column (after loading this in a table), all the keys of one type should be in colA.

I'm checking each word of the String array and copying them in a new string in a fixed position. The way I thought of doing this is using if else ladder like this:

//row is the tokenized unordered String

String[] newRow = new String[150];

for (int i = 0; i < row.length; ++i) {

if(row[i].equals("token1")){
newRow[0] = row[i]; //key
newRow[1] = row[i+1];//value
}

else if(row[i].equals("token2")){
newRow[2] = row[i];
newRow[3] = row[i+1];
}//...and so on. Elseif ladder at least is at least 100 long.


I wanted to know if there is a more efficient way to do this?

PS: I'm not sorting the string. Example: row1 String is {apple,good,banana,bad}, row2 String is {banana,good,apple,bad} where apple and banana are keys. Now in my output I will have two records with say apple as the first key and then banana. So output will be : newRow1: {apple,good,banana,bad}, newRow2: {apple,bad,banana,good}. Essentially I'm rearranging all input to a fixed output.

• I notice that the indentation of your original post has been fixed manually; I have written a bookmarklet to do this automatically. Would you mind if I use the original version as a test sample? It would be part of a jsfiddle and linked from a CR post, but not part of any distributed code. – sqykly Jan 28 '14 at 6:30

I'd put token names and positions in a Map like this:

Map<String, Integer> tokenIndexes = new HashMap<String, Integer>();
tokenIndexes.put("token1", 0);
tokenIndexes.put("token2", 2);
tokenIndexes.put("token3", 4);
// ...


and then in the "sorting" part:

String[] newRow = new String[150];

for (int i = 0; i < row.length; i+=2) { // go two by two as you have keys in even indexes
if(tokenIndexes.contains(row[i])) {
int index = tokenIndexes.get(row[i]);
newRow[index] = row[i];
newRow[index + 1] = row[i + 1];
} else {
// handle missing token
}
}


This way I would get rid of all "if-else" statements, although now I have to maintain a Map (which I think is easier than maintaining a list of "if-else").

UPDATE

I'm supposing you just receive that String array and you're unable to change the way the information is retrieved. If you can change the initial array with a Map that would simplify your code even further.

If that's the case then try this to capture your tokens instead of putting everything in an array (I'm supposing a key is the first token to appear):

Map<String, String> info = new HashTable<String, String>();
boolean isKey = true;
String lastKey = null;
String token;
while(tokensAvailable()  /* or (token = readToken()) != null */) {
if(isKey) {
lastKey = token;
} else {
info.put(lastKey, token);
}
isKey = !isKey;
}


And then when you have to print your table, you can do something like this:

printOut("VAL_1    --   VAL_2   --   VAL_3");
printOut(String.format("%08d  --  %10.2  -- %s", info.get("numericVal1"), info.get("monetaryVal2"), info.get("val3")));


String.format() is useful in these cases, you can control the format (like the width) of how every field is printed.

• I see... Let me try it.. – user221122 Jul 30 '13 at 1:12
• Just in case: remember that key's indexes must be even, odd positions are for values – morgano Jul 30 '13 at 1:35
• Yes, I can change the initial array. So I'm loading it in 'row' in a nested loop using row.append() – user221122 Jul 30 '13 at 2:09
• Updated again, have a try. – morgano Jul 30 '13 at 2:47
• Okay. So I think I need the hard coded HashMap at the top for having a fixed position. I'm putting the key-values in another HashMap. So now instead of comparing the string array row with the position based HashMap, I'll compare the HashMap with the position based HashMap. That way, I still get the fixed order. – user221122 Jul 30 '13 at 3:00