JAVA-23808 Rewrite Custom Spliterator Section of Introduction to Spliterator Article
This commit is contained in:
parent
b0ed62e8c8
commit
1a7d3aff21
|
@ -0,0 +1,48 @@
|
|||
package com.baeldung.spliterator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CustomSpliterator implements Spliterator<Integer> {
|
||||
private final List<Integer> elements;
|
||||
private int currentIndex;
|
||||
|
||||
public CustomSpliterator(List<Integer> elements) {
|
||||
this.elements = elements;
|
||||
this.currentIndex = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super Integer> action) {
|
||||
if (currentIndex < elements.size()) {
|
||||
action.accept(elements.get(currentIndex));
|
||||
currentIndex++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<Integer> trySplit() {
|
||||
int currentSize = elements.size() - currentIndex;
|
||||
if (currentSize < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int splitIndex = currentIndex + currentSize / 2;
|
||||
CustomSpliterator newSpliterator = new CustomSpliterator(elements.subList(currentIndex, splitIndex));
|
||||
currentIndex = splitIndex;
|
||||
return newSpliterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
return elements.size() - currentIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return ORDERED | SIZED | SUBSIZED | NONNULL;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package com.baeldung.spliterator;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Executor {
|
||||
|
||||
public static int countAutors(Stream<Author> stream) {
|
||||
RelatedAuthorCounter wordCounter = stream.reduce(new RelatedAuthorCounter(0, true),
|
||||
RelatedAuthorCounter::accumulate, RelatedAuthorCounter::combine);
|
||||
return wordCounter.getCounter();
|
||||
}
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package com.baeldung.spliterator;
|
||||
|
||||
public class RelatedAuthorCounter {
|
||||
private final int counter;
|
||||
private final boolean isRelated;
|
||||
|
||||
public RelatedAuthorCounter(int counter, boolean isRelated) {
|
||||
this.counter = counter;
|
||||
this.isRelated = isRelated;
|
||||
}
|
||||
|
||||
public RelatedAuthorCounter accumulate(Author author) {
|
||||
if (author.getRelatedArticleId() == 0) {
|
||||
return isRelated ? this : new RelatedAuthorCounter(counter, true);
|
||||
} else {
|
||||
return isRelated ? new RelatedAuthorCounter(counter + 1, false) : this;
|
||||
}
|
||||
}
|
||||
|
||||
public RelatedAuthorCounter combine(RelatedAuthorCounter RelatedAuthorCounter) {
|
||||
return new RelatedAuthorCounter(counter + RelatedAuthorCounter.counter, RelatedAuthorCounter.isRelated);
|
||||
}
|
||||
|
||||
public int getCounter() {
|
||||
return counter;
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package com.baeldung.spliterator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Spliterator;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class RelatedAuthorSpliterator implements Spliterator<Author> {
|
||||
private final List<Author> list;
|
||||
AtomicInteger current = new AtomicInteger();
|
||||
|
||||
public RelatedAuthorSpliterator(List<Author> list) {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(Consumer<? super Author> action) {
|
||||
|
||||
action.accept(list.get(current.getAndIncrement()));
|
||||
return current.get() < list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<Author> trySplit() {
|
||||
int currentSize = list.size() - current.get();
|
||||
if (currentSize < 10) {
|
||||
return null;
|
||||
}
|
||||
for (int splitPos = currentSize / 2 + current.intValue(); splitPos < list.size(); splitPos++) {
|
||||
if (list.get(splitPos).getRelatedArticleId() == 0) {
|
||||
Spliterator<Author> spliterator = new RelatedAuthorSpliterator(list.subList(current.get(), splitPos));
|
||||
current.set(splitPos);
|
||||
return spliterator;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() {
|
||||
return list.size() - current.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return CONCURRENT;
|
||||
}
|
||||
|
||||
}
|
|
@ -6,10 +6,10 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Spliterator;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -18,22 +18,50 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
public class ExecutorUnitTest {
|
||||
Article article;
|
||||
Stream<Author> stream;
|
||||
Spliterator<Author> spliterator;
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
article = new Article(Arrays.asList(new Author("Ahmad", 0), new Author("Eugen", 0), new Author("Alice", 1), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0),
|
||||
new Author("Alice", 1), new Author("Mike", 0), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1), new Author("Mike", 0), new Author("Alice", 1),
|
||||
new Author("Mike", 0), new Author("Michał", 0), new Author("Loredana", 1)), 0);
|
||||
|
||||
spliterator = new RelatedAuthorSpliterator(article.getListOfAuthors());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAstreamOfAuthors_whenProcessedInParallelWithCustomSpliterator_coubtProducessRightOutput() {
|
||||
Stream<Author> stream2 = StreamSupport.stream(spliterator, true);
|
||||
assertThat(Executor.countAutors(stream2.parallel())).isEqualTo(9);
|
||||
public void givenAStreamOfIntegers_whenProcessedSequentialCustomSpliterator_countProducesRightOutput() {
|
||||
List<Integer> numbers = new ArrayList<>();
|
||||
numbers.add(1);
|
||||
numbers.add(2);
|
||||
numbers.add(3);
|
||||
numbers.add(4);
|
||||
numbers.add(5);
|
||||
|
||||
CustomSpliterator customSpliterator = new CustomSpliterator(numbers);
|
||||
|
||||
AtomicInteger sum = new AtomicInteger();
|
||||
|
||||
customSpliterator.forEachRemaining(sum::addAndGet);
|
||||
assertThat(sum.get()).isEqualTo(15);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenAStreamOfIntegers_whenProcessedInParallelWithCustomSpliterator_countProducesRightOutput() {
|
||||
List<Integer> numbers = new ArrayList<>();
|
||||
numbers.add(1);
|
||||
numbers.add(2);
|
||||
numbers.add(3);
|
||||
numbers.add(4);
|
||||
numbers.add(5);
|
||||
|
||||
CustomSpliterator customSpliterator = new CustomSpliterator(numbers);
|
||||
|
||||
// Create a ForkJoinPool for parallel processing
|
||||
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();
|
||||
|
||||
AtomicInteger sum = new AtomicInteger(0);
|
||||
|
||||
// Process elements in parallel using parallelStream
|
||||
forkJoinPool.submit(() -> customSpliterator.forEachRemaining(sum::addAndGet)).join();
|
||||
assertThat(sum.get()).isEqualTo(15);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -43,9 +71,7 @@ public class ExecutorUnitTest {
|
|||
.collect(Collectors.toList());
|
||||
|
||||
Spliterator<Article> spliterator = articles.spliterator();
|
||||
while (spliterator.tryAdvance(article -> article.setName(article.getName()
|
||||
.concat("- published by Baeldung"))))
|
||||
;
|
||||
while(spliterator.tryAdvance(article -> article.setName(article.getName().concat("- published by Baeldung"))));
|
||||
|
||||
articles.forEach(article -> assertThat(article.getName()).isEqualTo("Java- published by Baeldung"));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue