@Test
  public void distinct() {
    LazyIterable<Integer> integers = Interval.oneTo(1000000000);

    Assert.assertEquals(FastList.newListWith(1, 2, 3, 4, 5), integers.distinct().take(5).toList());

    LazyIterable<Integer> lazyInterval = Interval.oneTo(1000000).flatCollect(Interval::oneTo);
    LazyIterable<Integer> distinct = lazyInterval.distinct();
    LazyIterable<Integer> take = distinct.take(5);
    Assert.assertEquals(Lists.immutable.of(1, 2, 3, 4, 5), take.toList());
  }
 @Test
 public void factorial() {
   Verify.assertThrows(IllegalStateException.class, () -> Interval.fromTo(-1, -5).factorial());
   Assert.assertEquals(1, Interval.zero().factorial().intValue());
   Assert.assertEquals(1, Interval.oneTo(1).factorial().intValue());
   Assert.assertEquals(6, Interval.oneTo(3).factorial().intValue());
   Assert.assertEquals(2432902008176640000L, Interval.oneTo(20).factorial().longValue());
   Assert.assertEquals(new BigInteger("51090942171709440000"), Interval.oneTo(21).factorial());
   Assert.assertEquals(
       new BigInteger("1405006117752879898543142606244511569936384000000000"),
       Interval.oneTo(42).factorial());
 }
 @Test
 public void forEachOnFromToInterval() {
   MutableList<Integer> result = Lists.mutable.of();
   Interval interval = Interval.oneTo(5);
   interval.forEach(CollectionAddProcedure.on(result));
   Assert.assertEquals(FastList.newListWith(1, 2, 3, 4, 5), result);
 }
 @Test
 public void forEachWithExecutor() {
   MutableList<Integer> result = Lists.mutable.of();
   Interval interval = Interval.oneTo(5);
   interval.forEach(CollectionAddProcedure.on(result), Executors.newSingleThreadExecutor());
   Assert.assertEquals(FastList.newListWith(1, 2, 3, 4, 5), result);
 }
 @Test
 public void collectOnFromToInterval() {
   Interval interval = Interval.oneTo(5);
   LazyIterable<String> result = interval.collect(String::valueOf);
   Verify.assertIterableSize(5, result);
   Verify.assertContainsAll(result, "1", "5");
 }
 @Test
 public void iterator() {
   Interval zero = Interval.zero();
   Iterator<Integer> zeroIterator = zero.iterator();
   Assert.assertTrue(zeroIterator.hasNext());
   Assert.assertEquals(Integer.valueOf(0), zeroIterator.next());
   Assert.assertFalse(zeroIterator.hasNext());
   Interval oneToFive = Interval.oneTo(5);
   Iterator<Integer> oneToFiveIterator = oneToFive.iterator();
   for (int i = 1; i < 6; i++) {
     Assert.assertTrue(oneToFiveIterator.hasNext());
     Assert.assertEquals(Integer.valueOf(i), oneToFiveIterator.next());
   }
   Verify.assertThrows(NoSuchElementException.class, (Runnable) oneToFiveIterator::next);
   Interval threeToNegativeThree = Interval.fromTo(3, -3);
   Iterator<Integer> threeToNegativeThreeIterator = threeToNegativeThree.iterator();
   for (int i = 3; i > -4; i--) {
     Assert.assertTrue(threeToNegativeThreeIterator.hasNext());
     Assert.assertEquals(Integer.valueOf(i), threeToNegativeThreeIterator.next());
   }
   Verify.assertThrows(
       NoSuchElementException.class, (Runnable) threeToNegativeThreeIterator::next);
   Verify.assertThrows(
       UnsupportedOperationException.class, () -> Interval.zeroTo(10).iterator().remove());
 }
 @Test
 public void reverseInjectIntoOnFromToByInterval() {
   Interval interval = Interval.oneTo(5);
   Assert.assertEquals(Integer.valueOf(20), interval.reverseInjectInto(5, AddFunction.INTEGER));
   Assert.assertEquals(
       Integer.valueOf(20), interval.reverseThis().reverseInjectInto(5, AddFunction.INTEGER));
 }
 @Test
 public void into() {
   int sum =
       Interval.oneTo(5)
           .select(Predicates.lessThan(5))
           .into(FastList.<Integer>newList())
           .injectInto(0, AddFunction.INTEGER_TO_INT);
   Assert.assertEquals(10, sum);
 }
 @Test
 public void run() {
   IntegerSum sum = new IntegerSum(0);
   Interval.oneTo(5).run(() -> sum.add(1));
   Assert.assertEquals(5, sum.getIntSum());
   IntegerSum sum2 = new IntegerSum(0);
   Interval.fromTo(5, 1).run(() -> sum2.add(1));
   Assert.assertEquals(5, sum2.getIntSum());
 }
 @Test
 public void runWithExecutor() throws InterruptedException {
   MutableList<String> result = Lists.mutable.of();
   ExecutorService service = Executors.newSingleThreadExecutor();
   Interval.oneTo(3).run(() -> result.add(null), service);
   service.shutdown();
   service.awaitTermination(20, TimeUnit.SECONDS);
   Assert.assertEquals(FastList.<String>newListWith(null, null, null), result);
 }
 @Test
 public void rejectOnFromToInterval() {
   Interval interval = Interval.oneTo(5);
   Assert.assertEquals(
       FastList.newListWith(1, 3, 5), interval.reject(IntegerPredicates.isEven()).toList());
   Assert.assertEquals(
       FastList.newListWith(5, 3, 1),
       interval.reverseThis().reject(IntegerPredicates.isEven()).toList());
 }
 @Test
 public void selectOnFromToInterval() {
   Interval interval = Interval.oneTo(5);
   Assert.assertEquals(
       FastList.newListWith(2, 4), interval.select(IntegerPredicates.isEven()).toList());
   Assert.assertEquals(
       FastList.newListWith(4, 2),
       interval.reverseThis().select(IntegerPredicates.isEven()).toList());
 }
  @Test
  public void equalsAndHashCode() {
    Interval interval1 = Interval.oneTo(5);
    Interval interval2 = Interval.oneTo(5);
    Interval interval3 = Interval.zeroTo(5);
    Verify.assertPostSerializedEqualsAndHashCode(interval1);
    Verify.assertEqualsAndHashCode(interval1, interval2);
    Assert.assertNotEquals(interval1, interval3);
    Assert.assertNotEquals(interval3, interval1);

    Verify.assertEqualsAndHashCode(Interval.fromToBy(1, 5, 2), Interval.fromToBy(1, 6, 2));
    Verify.assertEqualsAndHashCode(FastList.newListWith(1, 2, 3), Interval.fromTo(1, 3));
    Verify.assertEqualsAndHashCode(FastList.newListWith(3, 2, 1), Interval.fromTo(3, 1));

    Assert.assertNotEquals(FastList.newListWith(1, 2, 3, 4), Interval.fromTo(1, 3));
    Assert.assertNotEquals(FastList.newListWith(1, 2, 4), Interval.fromTo(1, 3));
    Assert.assertNotEquals(FastList.newListWith(3, 2, 0), Interval.fromTo(3, 1));

    Verify.assertEqualsAndHashCode(FastList.newListWith(-1, -2, -3), Interval.fromTo(-1, -3));
  }
 @Test
 public void forEachWith() {
   IntegerSum sum = new IntegerSum(0);
   Interval.oneTo(5)
       .forEachWith((Integer each, Integer parameter) -> sum.add(each + parameter), 0);
   Assert.assertEquals(15, sum.getIntSum());
   IntegerSum sum2 = new IntegerSum(0);
   Interval.fromTo(5, 1)
       .forEachWith((Integer each, Integer parameter) -> sum2.add(each + parameter), 0);
   Assert.assertEquals(15, sum2.getIntSum());
 }
  @Test
  public void forEachWithIndex() {
    IntegerSum sum = new IntegerSum(0);
    Interval.oneTo(5)
        .forEachWithIndex((ObjectIntProcedure<Integer>) (each, index) -> sum.add(each + index));
    Assert.assertEquals(25, sum.getIntSum());
    IntegerSum zeroSum = new IntegerSum(0);
    Interval.fromTo(0, -4)
        .forEachWithIndex((ObjectIntProcedure<Integer>) (each, index) -> zeroSum.add(each + index));
    Assert.assertEquals(0, zeroSum.getIntSum());

    Verify.assertThrows(
        IndexOutOfBoundsException.class, () -> Interval.zeroTo(10).forEachWithIndex(null, -1, 10));
  }
  @Test
  public void reverseForEachOnFromToInterval() {
    List<Integer> result = new ArrayList<>();
    Interval interval = Interval.oneTo(5);
    interval.reverseForEach(result::add);
    Verify.assertSize(5, result);
    Verify.assertContains(1, result);
    Verify.assertContains(5, result);
    Assert.assertEquals(Integer.valueOf(5), Iterate.getFirst(result));
    Assert.assertEquals(Integer.valueOf(1), Iterate.getLast(result));

    result.clear();
    interval.reverseThis().reverseForEach(result::add);
    Verify.assertSize(5, result);
    Verify.assertContains(1, result);
    Verify.assertContains(5, result);
    Assert.assertEquals(Integer.valueOf(1), Iterate.getFirst(result));
    Assert.assertEquals(Integer.valueOf(5), Iterate.getLast(result));
  }
  @Test
  public void contains() {
    Assert.assertTrue(Interval.zero().contains(0));
    Assert.assertTrue(Interval.oneTo(5).containsAll(1, 5));
    Assert.assertTrue(Interval.oneTo(5).containsNone(6, 7));
    Assert.assertFalse(Interval.oneTo(5).containsAll(1, 6));
    Assert.assertFalse(Interval.oneTo(5).containsNone(1, 6));
    Assert.assertFalse(Interval.oneTo(5).contains(0));
    Assert.assertTrue(Interval.fromTo(-1, -5).containsAll(-1, -5));
    Assert.assertFalse(Interval.fromTo(-1, -5).contains(1));

    Assert.assertTrue(Interval.zero().contains(Integer.valueOf(0)));
    Assert.assertFalse(Interval.oneTo(5).contains(Integer.valueOf(0)));
    Assert.assertFalse(Interval.fromTo(-1, -5).contains(Integer.valueOf(1)));

    Assert.assertFalse(Interval.zeroTo(5).contains(new Object()));
  }
 @Test
 public void sumInterval() {
   int sum = Interval.oneTo(5).injectInto(0, AddFunction.INTEGER_TO_INT);
   Assert.assertEquals(15, sum);
 }
 @Test
 public void maxInterval() {
   Integer value = Interval.oneTo(5).injectInto(0, Integer::max);
   Assert.assertEquals(5, value.intValue());
 }