diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java new file mode 100644 index 0000000000..8f36550bdc --- /dev/null +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingCollector.java @@ -0,0 +1,32 @@ +package com.baeldung.skippingelements; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BinaryOperator; +import java.util.stream.Collector; + +class SkippingCollector { + private static final BinaryOperator IGNORE_COMBINE = (a, b) -> a; + private final int skip; + private final List list = new ArrayList<>(); + private int currentIndex = 0; + private SkippingCollector(int skip) { + this.skip = skip; + } + + private void accept(String item) { + final int index = ++currentIndex % skip; + if (index == 0) + list.add(item); + } + private List getResult() { + return list; + } + + public static Collector> collector(int skip) { + return Collector.of(() -> new SkippingCollector(skip), + SkippingCollector::accept, + IGNORE_COMBINE, + SkippingCollector::getResult); + } +} diff --git a/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java new file mode 100644 index 0000000000..eb382367cc --- /dev/null +++ b/core-java-modules/core-java-streams-5/src/main/java/com/baeldung/skippingelements/SkippingElements.java @@ -0,0 +1,65 @@ +package com.baeldung.skippingelements; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public class SkippingElements { + + private SkippingElements() { + } + + public static List skipNthElementInListWithFilter(List sourceList, int n) { +return IntStream.range(0, sourceList.size()) + .filter(s -> (s + 1) % n == 0) + .mapToObj(sourceList::get) + .collect(Collectors.toList()); + } + + public static List skipNthElementInListWithIterate(List sourceList, int n) { +int limit = sourceList.size() / n; +return IntStream.iterate(n - 1, i -> (i + n)) + .limit(limit) + .mapToObj(sourceList::get) + .collect(Collectors.toList()); + } + + public static List skipNthElementInListWithSublist(List sourceList, int n) { +int limit = sourceList.size() / n; +return Stream.iterate(sourceList, s -> s.subList(n, s.size())) + .limit(limit) + .map(s -> s.get(n - 1)) + .collect(Collectors.toList()); + } + + public static List skipNthElementInListWithFor(List sourceList, int n) { +List result = new ArrayList<>(); +for (int i = n - 1; i < sourceList.size(); i += n) { + result.add(sourceList.get(i)); +} +return result; + } + + public static List skipNthElementInListWithIterator(Stream sourceStream, int n) { +List result = new ArrayList<>(); +final Iterator iterator = sourceStream.iterator(); +int count = 0; +while (iterator.hasNext()) { + if (count % n == n - 1) { + result.add(iterator.next()); + } else { + iterator.next(); + } + ++count; +} +return result; + } + +public static List skipNthElementInStreamWithCollector(Stream sourceStream, int n) { + return sourceStream.collect(SkippingCollector.collector(n)); +} + +} diff --git a/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java new file mode 100644 index 0000000000..2fd6adb0cf --- /dev/null +++ b/core-java-modules/core-java-streams-5/src/test/java/com/baeldung/skippingelements/SkippingElementsUnitTest.java @@ -0,0 +1,114 @@ +package com.baeldung.skippingelements; + + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import java.util.stream.Stream; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +class SkippingElementsUnitTest { + + private static Stream testSource() { + return Stream.of( + Arguments.of( + List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", + "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two", + "Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty", + "Thirty One", "Thirty Two", "Thirty Three"), + List.of("Three", "Six", "Nine", "Twelve", "Fifteen", "Eighteen", "Twenty One", "Twenty Four", "Twenty Seven", "Thirty", "Thirty Three"), + 3), + Arguments.of( + List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", + "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two", + "Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty", + "Thirty One", "Thirty Two", "Thirty Three"), + List.of("Five", "Ten", "Fifteen", "Twenty", "Twenty Five", "Thirty"), + 5), + Arguments.of( + List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", + "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two", + "Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty", + "Thirty One", "Thirty Two", "Thirty Three"), + List.of("One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", + "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty", "Twenty One", "Twenty Two", + "Twenty Three", "Twenty Four", "Twenty Five", "Twenty Six", "Twenty Seven", "Twenty Eight", "Twenty Nine", "Thirty", + "Thirty One", "Thirty Two", "Thirty Three"), + 1), + Arguments.of( + List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"), + List.of("Wednesday", "Saturday"), + 3), + Arguments.of( + List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"), + List.of("Friday"), + 5), + Arguments.of( + List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"), + List.of("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"), + 1), + Arguments.of( + List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", + "December"), + List.of("March", "June", "September", "December"), + 3), + Arguments.of( + List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", + "December"), + List.of("May", "October"), + 5), + Arguments.of( + List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", + "December"), + List.of("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", + "December"), + 1) + ); + } + + @ParameterizedTest + @MethodSource("testSource") + void givenListSkipNthElementInListWithFilterTestShouldFilterNthElement(List input, List expected, int n) { + final List actual = SkippingElements.skipNthElementInListWithFilter(input, n); + assertEquals(expected, actual); + } + + @ParameterizedTest + @MethodSource("testSource") + void givenListSkipNthElementInListWithIterateTestShouldFilterNthElement(List input, List expected, int n) { + final List actual = SkippingElements.skipNthElementInListWithIterate(input, n); + assertEquals(expected, actual); + } + + @ParameterizedTest + @MethodSource("testSource") + void givenListSkipNthElementInListWithSublistTestShouldFilterNthElement(List input, List expected, int n) { + final List actual = SkippingElements.skipNthElementInListWithSublist(input, n); + assertEquals(expected, actual); + } + + @ParameterizedTest + @MethodSource("testSource") + void givenListSkipNthElementInListWithForTestShouldFilterNthElement(List input, List expected, int n) { + final List actual = SkippingElements.skipNthElementInListWithFor(input, n); + assertEquals(expected, actual); + } + + @ParameterizedTest + @MethodSource("testSource") + void givenListSkipNthElementInStreamWithIteratorTestShouldFilterNthElement(List input, List expected, int n) { + final Stream inputStream = input.stream(); + final List actual = SkippingElements.skipNthElementInListWithIterator(inputStream, n); + assertEquals(expected, actual); + } + + @ParameterizedTest + @MethodSource("testSource") + void givenListSkipNthElementInStreamWithCollectorShouldFilterNthElement(List input, List expected, int n) { + final Stream inputStream = input.stream(); + final List actual = SkippingElements.skipNthElementInStreamWithCollector(inputStream, n); + assertEquals(expected, actual); + } +} \ No newline at end of file