5

Let's say we have the following method.

void some(int id, int... otherIds) {

}

How can I create a single IntStream with those two arguments?

IntStream.concat(
        IntStream.of(id),
        Optional.ofNullable(otherIds)
                .map(IntStream::of)
                .orElseGet(IntStream::empty)
);

It seems verbose. Do we have any concise idiom for that?

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
Jin Kwon
  • 20,295
  • 14
  • 115
  • 184

2 Answers2

5

When you need to deal with nullable stream-source, you might use Stream.ofNullable() accessible with Java 9, which produces either a singleton-stream or an empty stream. It'll be cleaner than utilizing Optional.ofNullable() for the purpose of chaining methods on it.

IntStream.concat(IntStream.of(id),
    Stream.ofNullable(otherIds).flatMapToInt(IntStream::of))

Another option is to make use of Java 9 static method Objects.requireNonNullElse() which expects a nullable argument and a default value:

IntStream.concat(IntStream.of(id),
    IntStream.of(Objects.requireNonNullElse(otherIds, new int[0])))

And the simplest and cleanest solution will be a fail-fast implementation, that will throw a NullPointerException in case if array otherIds is null.

IntStream.concat(IntStream.of(id), Arrays.stream(otherIds))

A null-safe flavor of it (credits to @Holger):

IntStream.concat(IntStream.of(id),
                 otherIds != null ? Arrays.stream(otherIds) : IntStream.empty())
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • 1
    Varargs can be null. – Markus Weninger May 05 '22 at 04:18
  • 1
    @MarkusWeninger Correct, removing the second part. – Alexander Ivanchenko May 05 '22 at 04:21
  • @OleV.V. My comment was regarding an earlier version of the answer in which it stated "varargs parameters cannot be null" (which I just wanted to clarify that they can), Alexander Ivanchenko already fixed the answer well. – Markus Weninger May 05 '22 at 07:22
  • 1
    @OleV.V. Thanks. Restored the removed part. The decision to delete a fail-fast solution completely was a kind of strange spark in a sleepy brain. Personally, I think this approach is the cleanest one. Although it might not be helpful for OP (if they have, for instance, a part of a system that was designed to produce `null` to indicate the absence of data instead of an empty array, and therefore don't want to treat this case as abnormal). – Alexander Ivanchenko May 05 '22 at 14:20
  • 2
    @MarkusWeninger The array reference can be `null` when the caller passes a `null` array reference, but that’s not a *varargs* call anymore. – Holger May 06 '22 at 09:11
  • 2
    I’d use `Arrays.stream(otherIds)` instead of `IntStream.of(otherIds)` because `otherIds` is an existing array, so this is not a varargs call. Of course, the result will be the same. And when you want to handle `null`, consider `IntStream.concat(IntStream.of(id), otherIds != null? Arrays.stream(otherIds): IntStream.empty())` – Holger May 06 '22 at 09:13
  • @Holger I agree, from the perspective of self-describing code `Arrays.stream()` is a better stylistic choice than `IntStream.of()`. Thanks for this suggestion, I never paid attention to that before. Improved the answer. – Alexander Ivanchenko May 06 '22 at 14:05
1

Well, Alexander Ivanchenko has already mentioned three options.

Here's another one:

Objects.requireNonNull(otherIds);
Stream.of(new int[] { id }, otherIds)
    .flatMapToInt(Arrays::stream)

I think otherIds should not be null, and should be considered a programmer error. With Objects::requireNonNull it fails-fast.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130