1

For example, say I have the following String: "1 23 35 5d 8 0 f"

When I run the function, how can I extract an ArrayList<Integer> out of it so it will contain {1, 23, 35, 8, 0}, effectively skipping invalid integers?

If anything, the skipping invalid integers is not very important, as I can easily resolve that, but I'm mainly trying to see if there's an effective way to parse every integer from a String.

StoneMan
  • 423
  • 3
  • 18

4 Answers4

2

Nothing fancy. Just loop, and ignore exceptions:

List<Integer> list = new ArrayList<>();
for (String num : "1 23 35 5d 8 0 f".split(" ")) {
    try {
        list.add(Integer.parseInt(num));
    } catch (NumberFormatException e) {}
}

*Edit*: If invalid integers are common, you will get better performance using a manual check of the digits of each part:

List<Integer> list = new ArrayList<>();
outer:
for (String num : "1 23 35 5d 8 0 f".split(" ")) {
    for (int i = 0; i < num.length(); i++) {
        char c = num.charAt(i);
        if (!((c >= '0' && c <= '9') || c == '-' || c == '+')) continue outer;
    }
    try {
        list.add(Integer.parseInt(num));
    } catch (NumberFormatException e) {}
}

This still has the try-catch in order to reject out of range integers or any that have minus/plus signs in inappropriate places, but you can remove that if you know those don't occur in your data, or if you'd prefer to throw the exception for those cases.

Boann
  • 48,794
  • 16
  • 117
  • 146
  • @Ypnypn Yeah, sorry if I didn't mention it but performance is sort of important, so do you know of any other way? I was thinking of something along the lines of this, but I'm only going to use it if everything else is not worth the effort. – StoneMan Jul 28 '14 at 20:20
  • @user3ffgfgfgfgfg50064 It's not *that* slow once it gets warmed up. Try it. – Boann Jul 28 '14 at 20:21
  • 1
    If the `try/catch` is causing the performance problem (sorry, I don't know about details like this), one could always say `if (num.matches("\\d+"))` instead of relying on the exception. (Modify as needed if you have to allow signs.) – ajb Jul 28 '14 at 20:58
  • @ajb The regex object would need to be cached in a static final var to avoid repeated parsing, but even then, the regex check might be slower than just swallowing the exception. – Boann Jul 28 '14 at 21:00
2

If you don't want to write your own "is this a number" checker, you can use Apache Commons:

    List<Integer> list = new ArrayList<>();
    for (String num : "1 23 35 5d 8 0 f".split(" ")) {
        if (StringUtils.isNumeric(num)) {
            list.add(Integer.parseInt(num));
        }
    }

This has the advantage of not using exception handling to do flow control (which I find inelegant).

azurefrog
  • 10,785
  • 7
  • 42
  • 56
1

I would use a regex, the easy one would simply be to remove all non numeric/space characters, then simply split the string

Edit:

As pointed out in the comments this solution does not give the answer the questioner wanted. OK, an actual solution for this would be split the string on spaces then use a regex to insure all the digits in each string are numeric. This actually insures that not only are all the items numeric, but because we are also filtering out the . character the numbers in each of these are integers, there is no need to check the int at this point and it can simply be parsed

theDarse
  • 749
  • 5
  • 13
  • Then, use one of the answers from [here](http://stackoverflow.com/questions/237159/whats-the-best-way-to-check-to-see-if-a-string-represents-an-integer-in-java) – Ypnypn Jul 28 '14 at 20:24
  • 1
    Removing all non-numeric characters first would leave `5` in the input after removing the `d` from `5d`. This is not what the questioner wants. – ajb Jul 28 '14 at 20:59
0
public class Agent{
 public static void main(String...args){
    String input = "1 23 35 5d 8 0 f";
    List<Integer> intList = new ArrayList<Integer>();


    Arrays.asList(input.split(" ")).stream().forEach( i -> {
            try{
              intList.add(Integer.parseInt(i));
            }catch(Exception ex){

            }
    });

    intList.forEach( i -> System.out.print(" " + i));
}

}

Output:

1 23 35 8 0
Kick Buttowski
  • 6,709
  • 13
  • 37
  • 58