I've previously looked at how to work on a higher level by replacing loops with streams. In this post I want to continue this by looking at `IntStream`

and how it could replace the traditional `for (int i=0;...`

loop.

`IntStream`

is a stream of primitive int values. It's part of the `java.util.stream`

package, and you can find a lot of the same functions there as in the normal `Stream<T>`

. There also exists streams for dealing with *double* and *long* primitives, but we'll leave that out since it acts in pretty much the same way.

There are several ways of creating an `IntStream`

.

Let's start by looking at the `of`

function.

```
IntStream.of(1, 2, 3);
// > 1, 2, 3
```

`of`

just takes an arbitrary number of ints, creating an `IntStream`

based on them.

Usually we don't want to list up all the ints like this, so let's instead continue by looking at two functions that probably will be used most of the time.

```
IntStream.range(1, 3);
// > 1, 2
IntStream.rangeClosed(1, 3);
// > 1, 2, 3
```

With `range`

and `rangeClosed`

, we define a range of ints that we want to create a stream of.

As you probably guessed from the resulting streams, the `rangeClosed`

function includes the ending int, while `range`

excludes it.

Now what if we don't want all the ints within a range? What if we just want every even number?

Then we could use the `iterator`

function.

```
IntStream.iterate(0, i -> i + 2).limit(3);
// > 0, 2, 4
```

With `iterator`

we can define a start value and a function that will calculate the next ints based on the previous element.

`iterator`

creates an infinite stream, so I've used `limit`

to create a stream containing just three elements.

The last function we're going to cover for creating `IntStreams`

, is the `generate`

function.

```
IntStream.generate(() -> ThreadLocalRandom.current().nextInt(10)).limit(3);
// > 4, 1, 7
```

`generate`

looks a lot like `iterator`

, but differ by not calculating the ints based on the previous element.

It simply takes an `IntSupplier`

that will independently calculate the next int.

Now that we have seen how we can create an `IntStream`

, let's start to play with it by using some of the functions it offer.

First, let's use the normal `map`

function to find the squared value of all ints between 0 and 5.

```
IntStream.range(1, 5).map(i -> i * i);
// > 1, 4, 9, 16
```

The `map`

function maps to an `IntStream`

, so what about when we want to return other types of streams?

Well, then we have dedicated map functions to handle these scenarios

```
Stream<Color> stream = IntStream.range(1, 5).mapToObj(i -> getColor(i));
```

`mapToObject`

will simply return a `Stream`

of the type that the mapping returns.

Now, if you just want to convert an `IntStream`

to a `Stream<Integer>`

, there's a dedicated function for this job called `boxed`

.

```
Stream<Integer> stream = IntStream.range(1, 5).boxed();
```

You'll also find map functions that returns `DoubleStream`

and `LongStream`

.

```
DoubleStream stream = IntStream.range(1, 5).mapToDouble(i -> i);
LongStream stream = IntStream.range(1, 5).mapToLong(i -> i);
```

Let's start by using `anyMatch`

to confirm that a certain range contains at least one even number.

```
IntStream.range(1, 5).anyMatch(i -> i % 2 == 0);
// > true
```

`anyMatch`

will check if a predicate holds for at least one of the elements in the stream.

We also have two other match functions, `noneMatch`

and `allMatch`

, that should return false for this predicate.

```
IntStream.range(1, 5).allMatch(i -> i % 2 == 0);
// > false
IntStream.range(1, 5).noneMatch(i -> i % 2 == 0);
// > false
```

Great!

Let's now use the `filter`

function to filter all the even numbers, then confirm that the filter did it's job by using `allMatch`

to make sure all numbers are even. Let's also use `noneMatch`

to make sure we can't find any odd numbers.

```
IntStream.range(1, 5)
.filter(i -> i % 2 == 0)
.allMatch(i -> i % 2 == 0);
// > true
IntStream.range(1, 5)
.filter(i -> i % 2 == 0)
.noneMatch(i -> i % 2 != 0);
// > true
```

`IntStream`

contains functions for fetching the max and min value```
IntStream.range(1, 5).max().getAsInt();
// > 4
IntStream.range(1, 5).min().getAsInt();
// > 1
```

Both these methods and a lot of the other functions that returns one element, will return an `OptionalInt`

.

`OptionalInt`

, like `Optional`

, gives some great higher-order functions that are abstracting away the null checks. Since that's not the topic of this post, we'll just fetch the int value assuming it's there.

`IntStream`

also offers the excellent `reduce`

function```
IntStream.range(1, 5).reduce(1, (x, y) -> x * y)
// > 24
```

Here we reduce the stream by multiplying all the elements.

Another great thing about the Stream API, is that you can work on elements in parallel.

Let's say we have a heavy operation that we want to execute four times.

```
IntStream.range(1, 5).parallel().forEach(i -> heavyOperation());
```

`parallel`

will execute `heavyOperation`

in parallel for all the elements in the stream. Thanks to this `parallel`

, we can potentially save a great amount of time, with very little effort.