1

Say, I have an array similar to this,

{"A", "1", "B", "2", "C", "3"}

I want to put it to HashMap like pairs, I tried few ways, but none seem to work. I created a method isDigit() to check if an item is digit,

private static boolean isDigit(String str){
    try {
        Integer.parseInt(str);
    }
    catch (NumberFormatException nfe){
        return false;
    }
    return true;
}

Then I tried separating into 2 arrays, numbers and letters.

for (int i = 0; i <= parts.length; i++) {
    if (isDigit(parts[i])) {
        numbers[i] = parts[i];
    } else {
        abcs[i] = parts[i];
    }
}

and finally,

for (int i = 0; i < numbers.length ; i++) {
    map.put(abcs[i], numbers[i]);
}

and I print them with,

for (String each: map.keySet()) {
   System.out.println(each + ":" + map.get(each));
}

which prints something like,

1
A : null
2
B : null

What it should print is,

A : 1
B : 2
C : 3
5
  • "A"1"B"2"C"3" is not an array. Commented Apr 15, 2017 at 19:43
  • isDigit("10") would return true, but 10 isn't a digit. isInteger would be a better name. Commented Apr 15, 2017 at 19:47
  • 1
    You're making it much harder (and slower) than necessary. Why not just iterate through the original array, add the current element and the next one to the map, and then add 2 to the loop counter? for (int i = 0; i < array.length; i += 2) { map.put(array[i], array[i + 1]); } Commented Apr 15, 2017 at 19:48
  • @JB Nizet already tried that, let me edit the question with that as well. Commented Apr 15, 2017 at 19:49
  • There are ways to do this in various ways, your way is one of them, though its not the best one. Still as a learning you must try to know the error or issue in your code. I have added my answer and tried to explain the issue with the solution to resolve the issue. Hope it will be helpful. stackoverflow.com/a/43430604/504133 Commented Apr 15, 2017 at 19:55

5 Answers 5

2

Why not just iterate through the parts in pairs by incrementing the loop counter in 2s:

for (int i = 0; i < parts.length -1; i += 2) {
    map.put(parts[i], parts[i + 1]);
}
Sign up to request clarification or add additional context in comments.

12 Comments

Already tried this, say if I do, map.get("A");, prints 2 \n B.
I don't think you'll want to do this as you'll have to start keeping track of iterating by twos which is not common. While this option might work, it wouldn't pass code review.
You need to post the bit of code that creates the array. That sounds like the problem. "2 \n B" must be in the array for that to happen.
@GlenPierce IndexOutOfBoundsException you mean. I have now fixed that with a -1
@GlenPierce haha :D
|
2

The problem is with your for loop:

for (int i = 0; i <= parts.length; i++) {
    if (isDigit(parts[i])) {
        numbers[i] = parts[i];
    } else {
        abcs[i] = parts[i];
    }
}

You are iterating from 0 to 5, so what happens is you are placing valies into indexes offset by 1. It goes like this: abcs[0] -> numbers[1] -> abcs[2] -< numbers[3]. A simpler solution is to use lists and use the add method.

1 Comment

Agreed. Using a List would be better here.
1

Your iterating over the array unevenly.

for (int i = 0; i <= parts.length; i++) {
    if (isDigit(parts[i])) {
        numbers[i] = parts[i];
    } else {
        abcs[i] = parts[i];
    }
}

Assuming isDigit() is behaving, you're creating two arrays, but they aren't in order when you create them.

So when i == 0, isDigit(parts[0]) is false, so you create abcs[0] = parts[0], but the next item you create in abcs isn't abcs[1], it's abcs[2] because you skipped 1 when it was a digit.

Comments

0

There is the issue of indexing in your case. Though looking at the input type there are other ways (One such way is mentioned in an another answer) to do this but I am editing your code so that it could work as intended by you.

int inputLength = parts.length; // assuming it is always even as it contains a pair (alphabet, number)
int[] numbers = new int[inputLength/2];
char[] abcs = new char[inputLength/2;

int keyIndex = 0;
int valueIndex = 0;

for (int i = 0; i <= parts.length; i++) {
    if (isDigit(parts[i])) {
        numbers[keyIndex] = parts[i];
        keyIndex++;
    } else {
        abcs[valueIndex] = parts[i];
        valueIndex++;
    }
}

Comments

0

As it is mentioned in one of the answers Your iterating over the array unevenly the problem is with indexing in a loop. But I would like also to point out, that you are using exception handling in a wrong way in your method isDigit(String str) Using exception handling for control flow is considered as a bad practice. A good answer to the question about this topic is here: Exceptions as control flow I would refactor your method to something like this:

private static boolean isDigit(String str){
    if (Character.isDigit(str.charAt(0))) { //assuming that the length of str is always 1
        return true;
    }
    return false;
}

Hope this helps.

2 Comments

The length of string is not always 1.
Ok, then you may use regex. Something like this in isDigit method body: return str.matches("[-+]?\\d*\\.?\\d+"); It will consider strings like "120" or "0012" or "00.45" as valid digits. Probably you will adjust regex to your concrete needs. Anyway my key idea was to kindly inform you that exception handling as control flow is an anti pattern.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.