## 1. Overview

Sometimes we need to find numeric digits or full numbers in strings. We can do this with both regular expressions or certain library functions.

In this article, we'll **use regular expressions to find and extract numbers in strings**. We'll also cover some ways to count digits.

## 2. Counting Numeric Digits

Let's start by counting the digits found within a string.

### 2.1. Using Regular Expressions

We can use Java Regular Expressions to count the number of matches for a digit.

In regular expressions, **“***\d**“* matches “any single digit”. Let's use this expression to count digits in a string:

```
int countDigits(String stringToSearch) {
Pattern digitRegex = Pattern.compile("\\d");
Matcher countEmailMatcher = digitRegex.matcher(stringToSearch);
int count = 0;
while (countEmailMatcher.find()) {
count++;
}
return count;
}
```

Once we have defined a *Matcher* for the regex, we can use it in a loop to *find *and count all the matches. Let's test it:

```
int count = countDigits("64x6xxxxx453xxxxx9xx038x68xxxxxx95786xxx7986");
assertThat(count, equalTo(21));
```

### 2.2. Using the Google Guava *CharMatcher*

To use Guava, we first need to add the Maven dependency:

```
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
```

Guava provides the *CharMatcher.inRange* method for counting digits:

```
int count = CharMatcher.inRange('0', '9')
.countIn("64x6xxxxx453xxxxx9xx038x68xxxxxx95786xxx7986");
assertThat(count, equalTo(21));
```

## 3. Finding Numbers

Counting numbers requires patterns that capture all the digits of a valid numeric expression.

### 3.1. Finding Integers

To construct an expression to recognize integers, we must consider that **they can be positive or negative and consist of a sequence of one or more digits**. We also note that negative integers are preceded by a minus sign.

Thus, we can find integers by extending our regex to “*-?\d+*“. This pattern means “an optional minus sign, followed by one or more digits”.

Let's create an example method that uses this regex to find integers in a string:

```
List<String> findIntegers(String stringToSearch) {
Pattern integerPattern = Pattern.compile("-?\\d+");
Matcher matcher = integerPattern.matcher(stringToSearch);
List<String> integerList = new ArrayList<>();
while (matcher.find()) {
integerList.add(matcher.group());
}
return integerList;
}
```

Once we have created a *Matcher* on the regex, we use it in a loop to *find* all the integers in a string. We call *group* on each match to get all the integers.

Let's test *findIntegers*:

```
List<String> integersFound =
findIntegers("646xxxx4-53xxx34xxxxxxxxx-35x45x9xx3868xxxxxx-95786xxx79-86");
assertThat(integersFound)
.containsExactly("646", "4", "-53", "34", "-35", "45", "9", "3868", "-95786", "79", "-86");
```

### 3.2. Finding Decimal Numbers

To create a regex that finds decimal numbers, we need to consider the pattern of characters used when writing them.

If a decimal number is negative, it starts with a minus sign. This is followed by one or more digits and an optional fractional part. This fractional part starts with a decimal point, with another sequence of one or more digits after that.

We can define this using the regular expression *“-?\d+(\.\d+)?*“:

```
List<String> findDecimalNums(String stringToSearch) {
Pattern decimalNumPattern = Pattern.compile("-?\\d+(\\.\\d+)?");
Matcher matcher = decimalNumPattern.matcher(stringToSearch);
List<String> decimalNumList = new ArrayList<>();
while (matcher.find()) {
decimalNumList.add(matcher.group());
}
return decimalNumList;
}
```

Now we'll test *findDecimalNums*:

```
List<String> decimalNumsFound =
findDecimalNums("x7854.455xxxxxxxxxxxx-3x-553.00x53xxxxxxxxxxxxx3456xxxxxxxx3567.4xxxxx");
assertThat(decimalNumsFound)
.containsExactly("7854.455", "-3", "-553.00", "53", "3456", "3567.4");
```

## 4. Converting the Strings Found into Numeric Values

We may also wish to convert the found numbers into their Java types.

Let's convert our integer numbers into *Long* using *Stream* mapping:

```
LongStream integerValuesFound = findIntegers("x7854x455xxxxxxxxxxxx-3xxxxxx34x56")
.stream()
.mapToLong(Long::valueOf);
assertThat(integerValuesFound)
.containsExactly(7854L, 455L, -3L, 34L, 56L);
```

Next, we'll convert decimal numbers to *Double* in the same way:

```
DoubleStream decimalNumValuesFound = findDecimalNums("x7854.455xxxxxxxxxxxx-3xxxxxx34.56")
.stream()
.mapToDouble(Double::valueOf);
assertThat(decimalNumValuesFound)
.containsExactly(7854.455, -3.0, 34.56);
```

## 5. Finding Other Types of Numbers

Numbers can be expressed in other formats, which we can detect by adjusting our regular expressions.

### 5.1. Scientific Notation

Let's find some numbers formatted using scientific notation:

```
String strToSearch = "xx1.25E-3xxx2e109xxx-70.96E+105xxxx-8.7312E-102xx919.3822e+31xxx";
Matcher matcher = Pattern.compile("-?\\d+(\\.\\d+)?[eE][+-]?\\d+")
.matcher(strToSearch);
// loop over the matcher
assertThat(sciNotationNums)
.containsExactly("1.25E-3", "2e109", "-70.96E+105", "-8.7312E-102", "919.3822e+31");
```

### 5.2. Hexadecimal

Now we'll find hexadecimal numbers in a string:

```
String strToSearch = "xaF851Bxxx-3f6Cxx-2Ad9eExx70ae19xxx";
Matcher matcher = Pattern.compile("-?[0-9a-fA-F]+")
.matcher(strToSearch);
// loop over the matcher
assertThat(hexNums)
.containsExactly("aF851B", "-3f6C", "-2Ad9eE", "70ae19");
```

## 6. Conclusion

In this article, we first discussed how to count digits in a string using regular expressions and the *CharMatcher* class from Google Guava.

Then, we explored using regular expressions to find integers and decimal numbers.

Finally, we covered finding numbers in other formats such as scientific notation and hexadecimal.

As always, the source code for this tutorial can be found over on GitHub.

res – REST with Spring (eBook) (everywhere)