private void basicReject(RichIterable<Integer> iterable) {
   Collection<Integer> actual1 = ParallelIterate.reject(iterable, Predicates.greaterThan(10000));
   Collection<Integer> actual2 =
       ParallelIterate.reject(
           iterable,
           Predicates.greaterThan(10000),
           HashBag.<Integer>newBag(),
           3,
           this.executor,
           true);
   Collection<Integer> actual3 =
       ParallelIterate.reject(iterable, Predicates.greaterThan(10000), true);
   RichIterable<Integer> expected = iterable.reject(Predicates.greaterThan(10000));
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual1.getClass().getSimpleName(),
       expected,
       actual1);
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual2.getClass().getSimpleName(),
       expected.toBag(),
       actual2);
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual3.getClass().getSimpleName(),
       expected.toBag(),
       HashBag.newBag(actual3));
 }
  @Test
  public void testForEachUsingSet() {
    // Tests the default batch size calculations
    IntegerSum sum = new IntegerSum(0);
    MutableSet<Integer> set = Interval.toSet(1, 10000);
    ParallelIterate.forEach(set, new SumProcedure(sum), new SumCombiner(sum));
    Assert.assertEquals(50005000, sum.getSum());

    // Testing batch size 1
    IntegerSum sum2 = new IntegerSum(0);
    UnifiedSet<Integer> set2 = UnifiedSet.newSet(Interval.oneTo(100));
    ParallelIterate.forEach(
        set2, new SumProcedure(sum2), new SumCombiner(sum2), 1, set2.getBatchCount(set2.size()));
    Assert.assertEquals(5050, sum2.getSum());

    // Testing an uneven batch size
    IntegerSum sum3 = new IntegerSum(0);
    UnifiedSet<Integer> set3 = UnifiedSet.newSet(Interval.oneTo(100));
    ParallelIterate.forEach(
        set3, new SumProcedure(sum3), new SumCombiner(sum3), 1, set3.getBatchCount(13));
    Assert.assertEquals(5050, sum3.getSum());

    // Testing divideByZero exception by passing 1 as batchSize
    IntegerSum sum4 = new IntegerSum(0);
    UnifiedSet<Integer> set4 = UnifiedSet.newSet(Interval.oneTo(100));
    ParallelIterate.forEach(set4, new SumProcedure(sum4), new SumCombiner(sum4), 1);
    Assert.assertEquals(5050, sum4.getSum());
  }
 private void basicCount(RichIterable<Integer> listIterable) {
   int actual1 = ParallelIterate.count(listIterable, Predicates.greaterThan(10000));
   int actual2 =
       ParallelIterate.count(listIterable, Predicates.greaterThan(10000), 11, this.executor);
   Assert.assertEquals(10000, actual1);
   Assert.assertEquals(10000, actual2);
 }
  @Test
  public void testForEachUsingMap() {
    // Test the default batch size calculations
    IntegerSum sum1 = new IntegerSum(0);
    MutableMap<String, Integer> map1 =
        Interval.fromTo(1, 10000).toMap(String::valueOf, Functions.getIntegerPassThru());
    ParallelIterate.forEach(map1, new SumProcedure(sum1), new SumCombiner(sum1));
    Assert.assertEquals(50005000, sum1.getSum());

    // Testing batch size 1
    IntegerSum sum2 = new IntegerSum(0);
    UnifiedMap<String, Integer> map2 =
        (UnifiedMap<String, Integer>)
            Interval.fromTo(1, 100).toMap(String::valueOf, Functions.getIntegerPassThru());
    ParallelIterate.forEach(
        map2, new SumProcedure(sum2), new SumCombiner(sum2), 1, map2.getBatchCount(map2.size()));
    Assert.assertEquals(5050, sum2.getSum());

    // Testing an uneven batch size
    IntegerSum sum3 = new IntegerSum(0);
    UnifiedMap<String, Integer> set3 =
        (UnifiedMap<String, Integer>)
            Interval.fromTo(1, 100).toMap(String::valueOf, Functions.getIntegerPassThru());
    ParallelIterate.forEach(
        set3, new SumProcedure(sum3), new SumCombiner(sum3), 1, set3.getBatchCount(13));
    Assert.assertEquals(5050, sum3.getSum());
  }
 @Test
 public void aggregateInPlaceBy() {
   Procedure2<AtomicInteger, Integer> countAggregator =
       (aggregate, value) -> aggregate.incrementAndGet();
   List<Integer> list = Interval.oneTo(20000);
   MutableMap<String, AtomicInteger> aggregation =
       ParallelIterate.aggregateInPlaceBy(list, EVEN_OR_ODD, ATOMIC_INTEGER_NEW, countAggregator);
   Assert.assertEquals(10000, aggregation.get("Even").intValue());
   Assert.assertEquals(10000, aggregation.get("Odd").intValue());
   ParallelIterate.aggregateInPlaceBy(
       list, EVEN_OR_ODD, ATOMIC_INTEGER_NEW, countAggregator, aggregation);
   Assert.assertEquals(20000, aggregation.get("Even").intValue());
   Assert.assertEquals(20000, aggregation.get("Odd").intValue());
 }
 private void executeParallelIterate(int level, ExecutorService executorService) {
   MutableList<Integer> items = Lists.mutable.of();
   for (int i = 0; i < 20000; i++) {
     items.add(i % 1000 == 0 ? level : 0);
   }
   ParallelIterate.forEach(items, new RecursiveProcedure(), executorService);
 }
  private class RecursiveProcedure implements Procedure<Integer> {
    private static final long serialVersionUID = 1L;
    private final ExecutorService executorService =
        ParallelIterate.newPooledExecutor("ParallelIterateTest", false);

    @Override
    public void value(Integer level) {
      if (level > 0) {
        ParallelIterateAcceptanceTest.this.threadNames.add(Thread.currentThread().getName());
        this.executeParallelIterate(level - 1, this.executorService);
      } else {
        this.simulateWork();
      }
    }

    private void simulateWork() {
      synchronized (ParallelIterateAcceptanceTest.this) {
        ParallelIterateAcceptanceTest.this.count++;
      }
    }

    private void executeParallelIterate(int level, ExecutorService executorService) {
      MutableList<Integer> items = Lists.mutable.of();
      for (int i = 0; i < 20000; i++) {
        items.add(i % 1000 == 0 ? level : 0);
      }
      ParallelIterate.forEach(items, new RecursiveProcedure(), executorService);
    }
  }
 @Test
 public void testForEachWithIndexToArrayUsingFixedArrayList() {
   Integer[] array = new Integer[10];
   List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
   Assert.assertTrue(ArrayIterate.allSatisfy(array, Predicates.isNull()));
   ParallelIterate.forEachWithIndex(list, (each, index) -> array[index] = each, 1, 2);
   Assert.assertArrayEquals(array, list.toArray(new Integer[list.size()]));
 }
 @Test
 public void testForEachWithIndexToArrayUsingArrayList() {
   Integer[] array = new Integer[200];
   List<Integer> list = new ArrayList<>(Interval.oneTo(200));
   Assert.assertTrue(ArrayIterate.allSatisfy(array, Predicates.isNull()));
   ParallelIterate.forEachWithIndex(list, (each, index) -> array[index] = each, 10, 10);
   Assert.assertArrayEquals(array, list.toArray(new Integer[] {}));
 }
 @Test
 public void selectSortedSet() {
   RichIterable<Integer> iterable = Interval.oneTo(20000).toSortedSet();
   Collection<Integer> actual1 = ParallelIterate.select(iterable, Predicates.greaterThan(10000));
   Collection<Integer> actual2 =
       ParallelIterate.select(iterable, Predicates.greaterThan(10000), true);
   RichIterable<Integer> expected = iterable.select(Predicates.greaterThan(10000));
   Assert.assertSame(expected.getClass(), actual1.getClass());
   Assert.assertSame(expected.getClass(), actual2.getClass());
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual1.getClass().getSimpleName(),
       expected,
       actual1);
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual2.getClass().getSimpleName(),
       expected,
       actual2);
 }
 @Test
 public void testForEachWithIndexException() {
   Verify.assertThrows(
       RuntimeException.class,
       () ->
           ParallelIterate.forEachWithIndex(
               ParallelIterateAcceptanceTest.createIntegerList(5),
               new PassThruObjectIntProcedureFactory<>(EXCEPTION_OBJECT_INT_PROCEDURE),
               new PassThruCombiner<>(),
               1,
               5));
 }
 private void basicCollectIf(RichIterable<Integer> collection) {
   Predicate<Integer> greaterThan = Predicates.greaterThan(10000);
   Collection<String> actual1 =
       ParallelIterate.collectIf(collection, greaterThan, String::valueOf);
   Collection<String> actual2 =
       ParallelIterate.collectIf(
           collection,
           greaterThan,
           String::valueOf,
           HashBag.<String>newBag(),
           3,
           this.executor,
           true);
   Collection<String> actual3 =
       ParallelIterate.collectIf(
           collection,
           greaterThan,
           String::valueOf,
           HashBag.<String>newBag(),
           3,
           this.executor,
           true);
   Bag<String> expected = collection.collectIf(greaterThan, String::valueOf).toBag();
   Verify.assertSize(10000, actual1);
   Verify.assertNotContains(String.valueOf(9000), actual1);
   Verify.assertNotContains(String.valueOf(21000), actual1);
   Verify.assertContains(String.valueOf(15976), actual1);
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual1.getClass().getSimpleName(),
       expected,
       HashBag.newBag(actual1));
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual2.getClass().getSimpleName(),
       expected,
       actual2);
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual3.getClass().getSimpleName(),
       expected,
       actual3);
 }
 private void basicCollect(RichIterable<Integer> iterable) {
   Collection<String> actual1 = ParallelIterate.collect(iterable, String::valueOf);
   Collection<String> actual2 =
       ParallelIterate.collect(
           iterable, String::valueOf, HashBag.<String>newBag(), 3, this.executor, false);
   Collection<String> actual3 = ParallelIterate.collect(iterable, String::valueOf, true);
   RichIterable<String> expected = iterable.collect(String::valueOf);
   Verify.assertSize(20000, actual1);
   Verify.assertContains(String.valueOf(20000), actual1);
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual1.getClass().getSimpleName(),
       expected,
       actual1);
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual2.getClass().getSimpleName(),
       expected.toBag(),
       actual2);
   Assert.assertEquals(
       expected.getClass().getSimpleName() + '/' + actual3.getClass().getSimpleName(),
       expected.toBag(),
       HashBag.newBag(actual3));
 }
 private void basicFlatCollect(RichIterable<Integer> iterable) {
   Collection<String> actual1 = ParallelIterate.flatCollect(iterable, INT_TO_TWO_STRINGS);
   Collection<String> actual2 =
       ParallelIterate.flatCollect(
           iterable, INT_TO_TWO_STRINGS, HashBag.<String>newBag(), 3, this.executor, false);
   Collection<String> actual3 = ParallelIterate.flatCollect(iterable, INT_TO_TWO_STRINGS, true);
   RichIterable<String> expected1 = iterable.flatCollect(INT_TO_TWO_STRINGS);
   RichIterable<String> expected2 =
       iterable.flatCollect(INT_TO_TWO_STRINGS, HashBag.<String>newBag());
   Verify.assertContains(String.valueOf(20000), actual1);
   Assert.assertEquals(
       expected1.getClass().getSimpleName() + '/' + actual1.getClass().getSimpleName(),
       expected1,
       actual1);
   Assert.assertEquals(
       expected2.getClass().getSimpleName() + '/' + actual2.getClass().getSimpleName(),
       expected2,
       actual2);
   Assert.assertEquals(
       expected1.getClass().getSimpleName() + '/' + actual3.getClass().getSimpleName(),
       expected1.toBag(),
       HashBag.newBag(actual3));
 }
 @Test
 public void aggregateInPlaceByWithBatchSize() {
   MutableList<Integer> list =
       LazyIterate.adapt(Collections.nCopies(1000, 1))
           .concatenate(Collections.nCopies(2000, 2))
           .concatenate(Collections.nCopies(3000, 3))
           .toList()
           .shuffleThis();
   MapIterable<String, AtomicInteger> aggregation =
       ParallelIterate.aggregateInPlaceBy(
           list, String::valueOf, ATOMIC_INTEGER_NEW, AtomicInteger::addAndGet, 100);
   Assert.assertEquals(1000, aggregation.get("1").intValue());
   Assert.assertEquals(4000, aggregation.get("2").intValue());
   Assert.assertEquals(9000, aggregation.get("3").intValue());
 }
  @Test
  public void testForEachImmutableList() {
    IntegerSum sum1 = new IntegerSum(0);
    ImmutableList<Integer> list1 =
        Lists.immutable.ofAll(ParallelIterateAcceptanceTest.createIntegerList(16));
    ParallelIterate.forEach(
        list1, new SumProcedure(sum1), new SumCombiner(sum1), 1, list1.size() / 2);
    Assert.assertEquals(16, sum1.getSum());

    IntegerSum sum2 = new IntegerSum(0);
    ImmutableList<Integer> list2 =
        Lists.immutable.ofAll(ParallelIterateAcceptanceTest.createIntegerList(7));
    ParallelIterate.forEach(list2, new SumProcedure(sum2), new SumCombiner(sum2));
    Assert.assertEquals(7, sum2.getSum());

    IntegerSum sum3 = new IntegerSum(0);
    ImmutableList<Integer> list3 =
        Lists.immutable.ofAll(ParallelIterateAcceptanceTest.createIntegerList(15));
    ParallelIterate.forEach(
        list3, new SumProcedure(sum3), new SumCombiner(sum3), 1, list3.size() / 2);
    Assert.assertEquals(15, sum3.getSum());

    IntegerSum sum4 = new IntegerSum(0);
    ImmutableList<Integer> list4 =
        Lists.immutable.ofAll(ParallelIterateAcceptanceTest.createIntegerList(35));
    ParallelIterate.forEach(list4, new SumProcedure(sum4), new SumCombiner(sum4));
    Assert.assertEquals(35, sum4.getSum());

    IntegerSum sum5 = new IntegerSum(0);
    ImmutableList<Integer> list5 = FastList.newList(list4).toImmutable();
    ParallelIterate.forEach(list5, new SumProcedure(sum5), new SumCombiner(sum5));
    Assert.assertEquals(35, sum5.getSum());

    IntegerSum sum6 = new IntegerSum(0);
    ImmutableList<Integer> list6 =
        Lists.immutable.ofAll(ParallelIterateAcceptanceTest.createIntegerList(40));
    ParallelIterate.forEach(
        list6, new SumProcedure(sum6), new SumCombiner(sum6), 1, list6.size() / 2);
    Assert.assertEquals(40, sum6.getSum());

    IntegerSum sum7 = new IntegerSum(0);
    ImmutableList<Integer> list7 = FastList.newList(list6).toImmutable();
    ParallelIterate.forEach(
        list7, new SumProcedure(sum7), new SumCombiner(sum7), 1, list6.size() / 2);
    Assert.assertEquals(40, sum7.getSum());
  }
  @Test
  public void groupBy() {
    FastList<Integer> iterable =
        FastList.newWithNValues(
            10000000,
            new Function0<Integer>() {
              private int current;

              public Integer value() {
                if (this.current < 4) {
                  return Integer.valueOf(this.current++);
                }
                this.current = 0;
                return Integer.valueOf(4);
              }
            });
    iterable.shuffleThis();
    Multimap<String, Integer> expected = iterable.toBag().groupBy(String::valueOf);
    Multimap<String, Integer> expectedAsSet = iterable.toSet().groupBy(String::valueOf);
    Multimap<String, Integer> result1 =
        ParallelIterate.groupBy(iterable.toList(), String::valueOf, 100);
    Assert.assertEquals(expected, HashBagMultimap.newMultimap(result1));
    Multimap<String, Integer> result2 = ParallelIterate.groupBy(iterable.toList(), String::valueOf);
    Assert.assertEquals(expected, HashBagMultimap.newMultimap(result2));
    Multimap<String, Integer> result3 =
        ParallelIterate.groupBy(
            iterable.toSet(),
            String::valueOf,
            SynchronizedPutUnifiedSetMultimap.<String, Integer>newMultimap(),
            100);
    Assert.assertEquals(expectedAsSet, result3);
    Multimap<String, Integer> result4 =
        ParallelIterate.groupBy(
            iterable.toSet(),
            String::valueOf,
            SynchronizedPutUnifiedSetMultimap.<String, Integer>newMultimap());
    Assert.assertEquals(expectedAsSet, result4);
    Multimap<String, Integer> result5 =
        ParallelIterate.groupBy(
            iterable.toSortedSet(),
            String::valueOf,
            SynchronizedPutUnifiedSetMultimap.<String, Integer>newMultimap(),
            100);
    Assert.assertEquals(expectedAsSet, result5);
    Multimap<String, Integer> result6 =
        ParallelIterate.groupBy(
            iterable.toSortedSet(),
            String::valueOf,
            SynchronizedPutUnifiedSetMultimap.<String, Integer>newMultimap());
    Assert.assertEquals(expectedAsSet, result6);
    Multimap<String, Integer> result7 =
        ParallelIterate.groupBy(
            iterable.toBag(),
            String::valueOf,
            SynchronizedPutHashBagMultimap.<String, Integer>newMultimap(),
            100);
    Assert.assertEquals(expected, result7);
    Multimap<String, Integer> result8 =
        ParallelIterate.groupBy(
            iterable.toBag(),
            String::valueOf,
            SynchronizedPutHashBagMultimap.<String, Integer>newMultimap());
    Assert.assertEquals(expected, result8);
    Multimap<String, Integer> result9 =
        ParallelIterate.groupBy(iterable.toList().toImmutable(), String::valueOf);
    Assert.assertEquals(expected, HashBagMultimap.newMultimap(result9));
    Multimap<String, Integer> result10 =
        ParallelIterate.groupBy(iterable.toSortedList(), String::valueOf, 100);
    Assert.assertEquals(expected, HashBagMultimap.newMultimap(result10));
    Multimap<String, Integer> result11 =
        ParallelIterate.groupBy(iterable.toSortedList(), String::valueOf);
    Assert.assertEquals(expected, HashBagMultimap.newMultimap(result11));

    Multimap<String, Integer> result12 =
        ParallelIterate.groupBy(
            iterable,
            String::valueOf,
            MultiReaderFastListMultimap.<String, Integer>newMultimap(),
            100);
    Assert.assertEquals(expected, HashBagMultimap.newMultimap(result12));
    Multimap<String, Integer> result13 =
        ParallelIterate.groupBy(
            iterable, String::valueOf, MultiReaderFastListMultimap.<String, Integer>newMultimap());
    Assert.assertEquals(expected, HashBagMultimap.newMultimap(result13));

    Multimap<String, Integer> result14 =
        ParallelIterate.groupBy(
            iterable,
            String::valueOf,
            MultiReaderHashBagMultimap.<String, Integer>newMultimap(),
            100);
    Assert.assertEquals(expected, result14);
    Multimap<String, Integer> result15 =
        ParallelIterate.groupBy(
            iterable, String::valueOf, MultiReaderHashBagMultimap.<String, Integer>newMultimap());
    Assert.assertEquals(expected, result15);

    Multimap<String, Integer> result16 =
        ParallelIterate.groupBy(
            iterable,
            String::valueOf,
            MultiReaderUnifiedSetMultimap.<String, Integer>newMultimap(),
            100);
    Assert.assertEquals(expectedAsSet, result16);
    Multimap<String, Integer> result17 =
        ParallelIterate.groupBy(
            iterable,
            String::valueOf,
            MultiReaderUnifiedSetMultimap.<String, Integer>newMultimap());
    Assert.assertEquals(expectedAsSet, result17);
  }