title: Properly handling empty Observable in RxJava
body: <p>I have a situation where I am creating an Observable containing results from a database. I am then applying a series of filters to them. I then have a subscriber that is logging the results. It may be the case that no elements make their way though the filters. My business logic states this is not an error. However, when this happens my onError is called and contains the following exception: <code>java.util.NoSuchElementException: Sequence contains no elements</code></p>
  
  <p>Is the accepted practice to just detect that type of exception and ignore it? Or is there a better way to handle this?</p>
  
  <p>The version is 1.0.0.</p>
  
  <p>Here is a simple test case that exposes what I'm seeing. It appears to be related to having all the events filtered before reaching a map and reduce.</p>
  
  <pre><code>  @Test
  public void test()
  {
  
      Integer values[] = new Integer[]{1, 2, 3, 4, 5};
  
      Observable.from(values).filter(new Func1&lt;Integer, Boolean&gt;()
      {
          @Override
          public Boolean call(Integer integer)
          {
              if (integer &lt; 0)
                  return true;
              else
                  return false;
          }
      }).map(new Func1&lt;Integer, String&gt;()
      {
          @Override
          public String call(Integer integer)
          {
              return String.valueOf(integer);
          }
      }).reduce(new Func2&lt;String, String, String&gt;()
      {
          @Override
          public String call(String s, String s2)
          {
              return s + "," + s2;
          }
      })
  
              .subscribe(new Action1&lt;String&gt;()
              {
                  @Override
                  public void call(String s)
                  {
                      System.out.println(s);
                  }
              });
  }
  </code></pre>
  
  <p>Because I am using a safe subscriber, it initially throws an OnErrorNotImplementedException which wraps the following exception:</p>
  
  <pre><code>java.util.NoSuchElementException: Sequence contains no elements
      at rx.internal.operators.OperatorSingle$1.onCompleted(OperatorSingle.java:82)
      at rx.internal.operators.NotificationLite.accept(NotificationLite.java:140)
      at rx.internal.operators.TakeLastQueueProducer.emit(TakeLastQueueProducer.java:73)
      at rx.internal.operators.TakeLastQueueProducer.startEmitting(TakeLastQueueProducer.java:45)
      at rx.internal.operators.OperatorTakeLast$1.onCompleted(OperatorTakeLast.java:59)
      at rx.internal.operators.OperatorScan$2.onCompleted(OperatorScan.java:121)
      at rx.internal.operators.OperatorMap$1.onCompleted(OperatorMap.java:43)
      at rx.internal.operators.OperatorFilter$1.onCompleted(OperatorFilter.java:42)
      at rx.internal.operators.OnSubscribeFromIterable$IterableProducer.request(OnSubscribeFromIterable.java:79)
      at rx.internal.operators.OperatorScan$2$1.request(OperatorScan.java:147)
      at rx.Subscriber.setProducer(Subscriber.java:139)
      at rx.internal.operators.OperatorScan$2.setProducer(OperatorScan.java:139)
      at rx.Subscriber.setProducer(Subscriber.java:133)
      at rx.Subscriber.setProducer(Subscriber.java:133)
      at rx.internal.operators.OnSubscribeFromIterable.call(OnSubscribeFromIterable.java:47)
      at rx.internal.operators.OnSubscribeFromIterable.call(OnSubscribeFromIterable.java:33)
      at rx.Observable$1.call(Observable.java:144)
      at rx.Observable$1.call(Observable.java:136)
      at rx.Observable$1.call(Observable.java:144)
      at rx.Observable$1.call(Observable.java:136)
      at rx.Observable$1.call(Observable.java:144)
      at rx.Observable$1.call(Observable.java:136)
      at rx.Observable$1.call(Observable.java:144)
      at rx.Observable$1.call(Observable.java:136)
      at rx.Observable$1.call(Observable.java:144)
      at rx.Observable$1.call(Observable.java:136)
      at rx.Observable.subscribe(Observable.java:7284)
  </code></pre>
  
  <p>Based on the answer from @davem below, I created a new test case:</p>
  
  <pre><code>@Test
  public void testFromBlockingAndSingle()
  {
  
      Integer values[] = new Integer[]{-2, -1, 0, 1, 2, 3, 4, 5};
  
      List&lt;String&gt; results = Observable.from(values).filter(new Func1&lt;Integer, Boolean&gt;()
      {
          @Override
          public Boolean call(Integer integer)
          {
              if (integer &lt; 0)
                  return true;
              else
                  return false;
          }
      }).map(new Func1&lt;Integer, String&gt;()
      {
          @Override
          public String call(Integer integer)
          {
              return String.valueOf(integer);
          }
      }).reduce(new Func2&lt;String, String, String&gt;()
      {
          @Override
          public String call(String s, String s2)
          {
              return s + "," + s2;
          }
      }).toList().toBlocking().single();
  
      System.out.println("Test: " + results + " Size: " + results.size());
  
  }
  </code></pre>
  
  <p>And this test results in the following behavior:</p>
  
  <p>When the input is:</p>
  
  <pre><code>Integer values[] = new Integer[]{-2, -1, 0, 1, 2, 3, 4, 5};
  </code></pre>
  
  <p>Then the results (as expected) are:</p>
  
  <pre><code>Test: [-2,-1] Size: 1
  </code></pre>
  
  <p>And when the input is:</p>
  
  <pre><code>Integer values[] = new Integer[]{0, 1, 2, 3, 4, 5};
  </code></pre>
  
  <p>Then the result is the following stack trace:</p>
  
  <pre><code>java.util.NoSuchElementException: Sequence contains no elements
  at rx.internal.operators.OperatorSingle$1.onCompleted(OperatorSingle.java:82)
  at rx.internal.operators.NotificationLite.accept(NotificationLite.java:140)
  at rx.internal.operators.TakeLastQueueProducer.emit(TakeLastQueueProducer.java:73)
  at rx.internal.operators.TakeLastQueueProducer.startEmitting(TakeLastQueueProducer.java:45)
  at rx.internal.operators.OperatorTakeLast$1.onCompleted(OperatorTakeLast.java:59)
  at rx.internal.operators.OperatorScan$2.onCompleted(OperatorScan.java:121)
  at rx.internal.operators.OperatorMap$1.onCompleted(OperatorMap.java:43)
  at rx.internal.operators.OperatorFilter$1.onCompleted(OperatorFilter.java:42)
  at rx.internal.operators.OnSubscribeFromIterable$IterableProducer.request(OnSubscribeFromIterable.java:79)
  at rx.internal.operators.OperatorScan$2$1.request(OperatorScan.java:147)
  at rx.Subscriber.setProducer(Subscriber.java:139)
  at rx.internal.operators.OperatorScan$2.setProducer(OperatorScan.java:139)
  at rx.Subscriber.setProducer(Subscriber.java:133)
  at rx.Subscriber.setProducer(Subscriber.java:133)
  at rx.internal.operators.OnSubscribeFromIterable.call(OnSubscribeFromIterable.java:47)
  at rx.internal.operators.OnSubscribeFromIterable.call(OnSubscribeFromIterable.java:33)
  at rx.Observable$1.call(Observable.java:144)
  at rx.Observable$1.call(Observable.java:136)
  at rx.Observable$1.call(Observable.java:144)
  at rx.Observable$1.call(Observable.java:136)
  at rx.Observable$1.call(Observable.java:144)
  at rx.Observable$1.call(Observable.java:136)
  at rx.Observable$1.call(Observable.java:144)
  at rx.Observable$1.call(Observable.java:136)
  at rx.Observable$1.call(Observable.java:144)
  at rx.Observable$1.call(Observable.java:136)
  at rx.Observable$1.call(Observable.java:144)
  at rx.Observable$1.call(Observable.java:136)
  at rx.Observable$1.call(Observable.java:144)
  at rx.Observable$1.call(Observable.java:136)
  at rx.Observable.subscribe(Observable.java:7284)
  at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:441)
  at rx.observables.BlockingObservable.single(BlockingObservable.java:340)
  at EmptyTest2.test(EmptyTest2.java:19)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
  at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
  at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
  at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
  at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
  at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
  at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
  </code></pre>
  
  <p>So it appears that the problem is definitely with the use of the reduce function. See the following test case that handles both situations:</p>
  
  <pre><code>@Test
  public void testNoReduce()
  {
  
      Integer values[] = new Integer[]{-2, -1, 0, 1, 2, 3, 4, 5};
  
      List&lt;String&gt; results = Observable.from(values).filter(new Func1&lt;Integer, Boolean&gt;()
      {
          @Override
          public Boolean call(Integer integer)
          {
              if (integer &lt; 0)
                  return true;
              else
                  return false;
          }
      }).map(new Func1&lt;Integer, String&gt;()
      {
          @Override
          public String call(Integer integer)
          {
              return String.valueOf(integer);
          }
      }).toList().toBlocking().first();
  
      Iterator&lt;String&gt; itr = results.iterator();
      StringBuilder b = new StringBuilder();
  
      while (itr.hasNext())
      {
          b.append(itr.next());
  
          if (itr.hasNext())
              b.append(",");
      }
  
      System.out.println("Test NoReduce: " + b);
  
  }
  </code></pre>
  
  <p>With the following input:</p>
  
  <pre><code>Integer values[] = new Integer[]{-2, -1, 0, 1, 2, 3, 4, 5};
  </code></pre>
  
  <p>I get the following results which are expected:</p>
  
  <pre><code>Test NoReduce: -2,-1
  </code></pre>
  
  <p>And with the following input:</p>
  
  <pre><code>Integer values[] = new Integer[]{0, 1, 2, 3, 4, 5};
  </code></pre>
  
  <p>I get the following output which are expected:</p>
  
  <pre><code>Test NoReduce: 
  </code></pre>
  
  <p>So, unless I am completely misunderstanding something, the only way to really handle a zero element Observable that results from a filter when followed by a map and reduce is to implement the reduce logic outside of the Observable chain. Do you all agree with that statement?</p>
  
  <hr>
  
  <p><strong>Final Solution</strong></p>
  
  <p>Here is my final solution after implementing what both Tomáš Dvořák and David Motten suggested. I think this solution is reasonable.</p>
  
  <pre><code>@Test
  public void testWithToList()
  {
  
      Integer values[] = new Integer[]{-2, -1, 0, 1, 2, 3, 4, 5};
  
       Observable.from(values).filter(new Func1&lt;Integer, Boolean&gt;()
       {
           @Override
           public Boolean call(Integer integer)
           {
               if (integer &lt; 0)
                   return true;
               else
                   return false;
           }
       }).toList().map(new Func1&lt;List&lt;Integer&gt;, String&gt;()
       {
           @Override
           public String call(List&lt;Integer&gt; integers)
           {
               Iterator&lt;Integer&gt; intItr = integers.iterator();
               StringBuilder b = new StringBuilder();
  
               while (intItr.hasNext())
               {
                   b.append(intItr.next());
  
                   if (intItr.hasNext())
                   {
                       b.append(",");
                   }
               }
  
               return b.toString();
           }
       }).subscribe(new Action1&lt;String&gt;()
       {
           @Override
           public void call(String s)
           {
               System.out.println("With a toList: " + s);
           }
       });
  
  }
  </code></pre>
  
  <p>Here is how this test behaves when given the following inputs.</p>
  
  <p>When given a stream that will have some values pass through the filters:</p>
  
  <pre><code>Integer values[] = new Integer[]{-2, -1, 0, 1, 2, 3, 4, 5};
  </code></pre>
  
  <p>The result is:</p>
  
  <pre><code>With a toList: -2,-1
  </code></pre>
  
  <p>When given a stream that will not have any values pass through the filters:</p>
  
  <pre><code>Integer values[] = new Integer[]{0, 1, 2, 3, 4, 5};
  </code></pre>
  
  <p>The result is:</p>
  
  <pre><code>With a toList: &lt;empty string&gt;
  </code></pre>