From 07aad444ae0052331349e53253ae0347e5912e28 Mon Sep 17 00:00:00 2001 From: Ahmad Alsanie Date: Fri, 12 Jan 2018 23:05:49 +0200 Subject: [PATCH] BAEL-1473 Intoduction to Spliterator in Java (#3400) --- .../com/baeldung/spliteratorAPI/Article.java | 44 +++++++++++++++++ .../com/baeldung/spliteratorAPI/Author.java | 33 +++++++++++++ .../com/baeldung/spliteratorAPI/Executor.java | 45 ++++++++++++++++++ .../spliteratorAPI/RelatedAuthorCounter.java | 27 +++++++++++ .../RelatedAuthorSpliterator.java | 47 +++++++++++++++++++ .../com/baeldung/spliteratorAPI/Task.java | 26 ++++++++++ 6 files changed, 222 insertions(+) create mode 100644 core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java create mode 100644 core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java create mode 100644 core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java create mode 100644 core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java create mode 100644 core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java create mode 100644 core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java new file mode 100644 index 0000000000..402ec6ec5f --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Article.java @@ -0,0 +1,44 @@ +package com.baeldung.spliteratorAPI; + +import java.util.List; + +public class Article { + private List listOfAuthors; + private int id; + private String name; + + public Article(String name) { + this.name = name; + } + + public Article(List listOfAuthors, int id) { + super(); + this.listOfAuthors = listOfAuthors; + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public List getListOfAuthors() { + return listOfAuthors; + } + + public void setListOfAuthors(List listOfAuthors) { + this.listOfAuthors = listOfAuthors; + } + +} \ No newline at end of file diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java new file mode 100644 index 0000000000..40c381f4a6 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Author.java @@ -0,0 +1,33 @@ +package com.baeldung.spliteratorAPI; + +public class Author { + private String name; + private int relatedArticleId; + + public Author(String name, int relatedArticleId) { + this.name = name; + this.relatedArticleId = relatedArticleId; + } + + public int getRelatedArticleId() { + return relatedArticleId; + } + + public void setRelatedArticleId(int relatedArticleId) { + this.relatedArticleId = relatedArticleId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "[name: " + name + ", relatedId: " + relatedArticleId + "]"; + } +} + diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java new file mode 100644 index 0000000000..b906acfad9 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Executor.java @@ -0,0 +1,45 @@ +package com.baeldung.spliteratorAPI; + +import java.util.Arrays; +import java.util.List; +import java.util.Spliterator; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public class Executor { + public void executeCustomSpliterator() { + Article 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); + Stream stream = IntStream.range(0, article.getListOfAuthors() + .size()) + .mapToObj(article.getListOfAuthors()::get); + System.out.println("count= " + countAutors(stream.parallel())); + Spliterator spliterator = new RelatedAuthorSpliterator(article.getListOfAuthors()); + Stream stream2 = StreamSupport.stream(spliterator, true); + System.out.println("count= " + countAutors(stream2.parallel())); + } + + public void executeSpliterator() { + Spliterator
split1 = generateElements().spliterator(); + Spliterator
split2 = split1.trySplit(); + ExecutorService service = Executors.newCachedThreadPool(); + service.execute(new Task(split1)); + service.execute(new Task(split2)); + } + + private static int countAutors(Stream stream) { + RelatedAuthorCounter wordCounter = stream.reduce(new RelatedAuthorCounter(0, true), RelatedAuthorCounter::accumulate, RelatedAuthorCounter::combine); + return wordCounter.getCounter(); + } + + private List
generateElements() { + return Stream.generate(() -> new Article("Java")) + .limit(35000) + .collect(Collectors.toList()); + } +} diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java new file mode 100644 index 0000000000..b7120b3af2 --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorCounter.java @@ -0,0 +1,27 @@ +package com.baeldung.spliteratorAPI; + +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; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java new file mode 100644 index 0000000000..ae91c6fe6c --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/RelatedAuthorSpliterator.java @@ -0,0 +1,47 @@ +package com.baeldung.spliteratorAPI; + +import java.util.List; +import java.util.Spliterator; +import java.util.function.Consumer; + +public class RelatedAuthorSpliterator implements Spliterator { + private final List list; + private int current = 0; + + public RelatedAuthorSpliterator(List list) { + this.list = list; + } + + @Override + public boolean tryAdvance(Consumer action) { + action.accept(list.get(current++)); + return current < list.size(); + } + + @Override + public Spliterator trySplit() { + int currentSize = list.size() - current; + if (currentSize < 10) { + return null; + } + for (int splitPos = currentSize / 2 + current; splitPos < list.size(); splitPos++) { + if (list.get(splitPos) + .getRelatedArticleId() == 0) { + Spliterator spliterator = new RelatedAuthorSpliterator(list.subList(current, splitPos)); + current = splitPos; + return spliterator; + } + } + return null; + } + + @Override + public long estimateSize() { + return list.size() - current; + } + + @Override + public int characteristics() { + return SIZED + CONCURRENT; + } +} diff --git a/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java new file mode 100644 index 0000000000..108fdc52aa --- /dev/null +++ b/core-java-8/src/main/java/com/baeldung/spliteratorAPI/Task.java @@ -0,0 +1,26 @@ +package com.baeldung.spliteratorAPI; + +import java.util.Spliterator; + +public class Task implements Runnable { + private Spliterator
spliterator; + private final static String SUFFIX = "- published by Baeldung"; + + public Task(Spliterator
spliterator) { + this.spliterator = spliterator; + } + + @Override + public void run() { + int current = 0; + while (spliterator.tryAdvance(article -> { + article.setName(article.getName() + .concat(SUFFIX)); + })) { + current++; + } + ; + System.out.println(Thread.currentThread() + .getName() + ":" + current); + } +}