2

I'm trying to exclude integers of a String which can be negative. I have tried this :

String numbersExcluded=input.replaceAll("[^-?0-9]+"," ");
String[] stringOfNumbers=numbersExcluded.trim().split(" ");

for (String each:stringOfNumbers)
     System.out.println(each);

but there is this when I give input like "aaa-4aaa5aaa?" the printing loop, prints

-4
5
?

why is ? included? how can I fix this?

byxor
  • 5,930
  • 4
  • 27
  • 44
fmatt
  • 464
  • 1
  • 5
  • 15
  • You have `?` in negated character class so it will obviously skip `?` in replacement. – anubhava Mar 03 '20 at 16:41
  • Your string says "Replace stuff that is not a minus, a question mark or a digit with a space". The question mark is in your exclusion list. – RealSkeptic Mar 03 '20 at 16:41
  • @RealSkeptic I meant "once or never" occurance by ? sign . then whats an alternative? – fmatt Mar 03 '20 at 16:43
  • Inside a character class, `?` does not have that meaning. I think a clearer alternative would be not to use split but rather a loop with `Matcher` and `find`. – RealSkeptic Mar 03 '20 at 16:44
  • @chuck2002 It will also allow strings like `---`. I think the OP wants to keep only strings that start with an optional minus followed by digits. – RealSkeptic Mar 03 '20 at 16:45
  • Why not just match things that *are* numbers? – kaya3 Mar 03 '20 at 16:46
  • @kaya3 how can I do that? – fmatt Mar 03 '20 at 16:49
  • Well, match `-?[0-9]+` for example, instead of negating the character class. That should be a lot easier than matching the parts you don't want in order to delete them. – kaya3 Mar 03 '20 at 16:50
  • thanks, grateful to all your help – fmatt Mar 03 '20 at 17:05

1 Answers1

4

I think replaceAll is not the correct choice here, I would suggest to use :

Pattern pattern = Pattern.compile("-?\\d+");
Matcher matcher = pattern.matcher("aaa-4aaa5aaa?");
List<Integer> result = new ArrayList<>();
while (matcher.find()) {
    result.add(Integer.parseInt(matcher.group()));
}

Or from Java-9+ you can use :

List<Integer> result = Pattern.compile("-?\\d+")
        .matcher("aaa-4aaa5aaa?")
        .results()
        .map(MatchResult::group)
        .map(Integer::valueOf)
        .collect(Collectors.toList());

Outputs

[-4, 5]
Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
  • This will remove all non-numbers, whether or not preceded with a `-`. The OP wishes to keep all numbers with or without a `-`. – RealSkeptic Mar 03 '20 at 16:46
  • I'd suggest keeping the `[0-9]` class rather than `\d`, since the latter matches anything Unicode considers to be a digit, most of which won't be valid for `Integer.parseInt`. – kaya3 Mar 03 '20 at 16:53
  • I agree @kaya3, but that for maximum security, I like \d as it is simple and clear. – Youcef LAIDANI Mar 03 '20 at 16:57
  • Not sure what you mean by security; allowing the user to cause a `NumberFormatException` to be thrown certainly can't improve the security of your application, but could degrade it if you're expecting the operation to always complete successfully. – kaya3 Mar 03 '20 at 16:58
  • 1
    thanks for your help – fmatt Mar 03 '20 at 17:04