BAEL-5674: added code examples for the article
This commit is contained in:
parent
a800f72b99
commit
536866c40b
|
@ -53,6 +53,12 @@
|
|||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
<version>${jmh-generator.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.12.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
package com.baeldung.streams.multiplefilters;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MultipleFiltersVsComplexConditionFilterOrderUnitTest {
|
||||
|
||||
AtomicInteger numberOfOperations = new AtomicInteger();
|
||||
|
||||
@Before
|
||||
public void beforeEach() {
|
||||
numberOfOperations.set(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenWrongFilterOrder_whenUsingMultipleFilters_shouldEvaluateManyConditions() {
|
||||
long filteredStreamSize = IntStream.range(0, 100)
|
||||
.boxed()
|
||||
.filter(this::isEvenNumber)
|
||||
.filter(this::isSmallerThanTwenty)
|
||||
.count();
|
||||
|
||||
assertThat(filteredStreamSize).isEqualTo(10);
|
||||
assertThat(numberOfOperations).hasValue(150);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenWrongFilterOrder_whenUsingSingleFilters_shouldEvaluateManyConditions() {
|
||||
long filteredStreamSize = IntStream.range(0, 100)
|
||||
.boxed()
|
||||
.filter(i -> isEvenNumber(i) && isSmallerThanTwenty(i))
|
||||
.count();
|
||||
|
||||
assertThat(filteredStreamSize).isEqualTo(10);
|
||||
assertThat(numberOfOperations).hasValue(150);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCorrectFilterOrder_whenUsingMultipleFilters_shouldEvaluateFewerConditions() {
|
||||
long filteredStreamSize = IntStream.range(0, 100)
|
||||
.boxed()
|
||||
.filter(this::isSmallerThanTwenty)
|
||||
.filter(this::isEvenNumber)
|
||||
.count();
|
||||
|
||||
assertThat(filteredStreamSize).isEqualTo(10);
|
||||
assertThat(numberOfOperations).hasValue(120);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCorrectFilterOrder_whenUsingHavingASlowCondition_shouldEvaluateFewerConditions() {
|
||||
long filteredStreamSize = IntStream.range(0, 100)
|
||||
.boxed()
|
||||
.filter(this::isSmallerThanTwenty)
|
||||
.filter(this::isEvenNumber)
|
||||
.filter(this::verySlowFilter)
|
||||
.count();
|
||||
|
||||
assertThat(filteredStreamSize).isEqualTo(10);
|
||||
assertThat(numberOfOperations).hasValue(130);
|
||||
}
|
||||
|
||||
private boolean isEvenNumber(int i) {
|
||||
numberOfOperations.incrementAndGet();
|
||||
return i % 2 == 0;
|
||||
}
|
||||
|
||||
private boolean isSmallerThanTwenty(int i) {
|
||||
numberOfOperations.incrementAndGet();
|
||||
return i < 20;
|
||||
}
|
||||
|
||||
private boolean verySlowFilter(int i) {
|
||||
numberOfOperations.incrementAndGet();
|
||||
// commented the Thread.sleep() not to slow down the pipeline.
|
||||
// try {
|
||||
// Thread.sleep(1000);
|
||||
// } catch (InterruptedException e) {
|
||||
// throw new RuntimeException(e);
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package com.baeldung.streams.multiplefilters;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.commons.lang3.time.StopWatch;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MultipleFiltersVsComplexConditionFilterPerformanceIntegrationTest {
|
||||
|
||||
// this test is slow, avoid running it on pipeline
|
||||
@Test
|
||||
public void measureProcessingTimeForEachSolution() {
|
||||
|
||||
averageMultipleMeasurements("Stream with Multiple Filters", this::measureTimeForMultipleFilters, 10_000);
|
||||
averageMultipleMeasurements("Stream with Multiple Filters", this::measureTimeForMultipleFilters, 100_000);
|
||||
averageMultipleMeasurements("Stream with Multiple Filters", this::measureTimeForMultipleFilters, 10_00_000);
|
||||
averageMultipleMeasurements("Stream with Multiple Filters", this::measureTimeForMultipleFilters, 1_0000_000);
|
||||
|
||||
averageMultipleMeasurements("Stream with Complex Condition", this::measureTimeForComplexCondition, 10_000);
|
||||
averageMultipleMeasurements("Stream with Complex Condition", this::measureTimeForComplexCondition, 100_000);
|
||||
averageMultipleMeasurements("Stream with Complex Condition", this::measureTimeForComplexCondition, 10_00_000);
|
||||
averageMultipleMeasurements("Stream with Complex Condition", this::measureTimeForComplexCondition, 1_0000_000);
|
||||
|
||||
averageMultipleMeasurements("Parallel Stream with Multiple Filters", this::measureTimeForParallelStreamWithMultipleFilters, 10_000);
|
||||
averageMultipleMeasurements("Parallel Stream with Multiple Filters", this::measureTimeForParallelStreamWithMultipleFilters, 100_000);
|
||||
averageMultipleMeasurements("Parallel Stream with Multiple Filters", this::measureTimeForParallelStreamWithMultipleFilters, 10_00_000);
|
||||
averageMultipleMeasurements("Parallel Stream with Multiple Filters", this::measureTimeForParallelStreamWithMultipleFilters, 1_0000_000);
|
||||
|
||||
averageMultipleMeasurements("Parallel Stream with Complex Condition", this::measureTimeForParallelStreamWithComplexCondition, 10_000);
|
||||
averageMultipleMeasurements("Parallel Stream with Complex Condition", this::measureTimeForParallelStreamWithComplexCondition, 100_000);
|
||||
averageMultipleMeasurements("Parallel Stream with Complex Condition", this::measureTimeForParallelStreamWithComplexCondition, 10_00_000);
|
||||
averageMultipleMeasurements("Parallel Stream with Complex Condition", this::measureTimeForParallelStreamWithComplexCondition, 1_0000_000);
|
||||
|
||||
averageMultipleMeasurements("Old For Loop with Complex Condition", this::measureTimeForOlfForLoopWithComplexCondition, 10_000);
|
||||
averageMultipleMeasurements("Old For Loop with Complex Condition", this::measureTimeForOlfForLoopWithComplexCondition, 100_000);
|
||||
averageMultipleMeasurements("Old For Loop with Complex Condition", this::measureTimeForOlfForLoopWithComplexCondition, 10_00_000);
|
||||
averageMultipleMeasurements("Old For Loop with Complex Condition", this::measureTimeForOlfForLoopWithComplexCondition, 1_0000_000);
|
||||
|
||||
}
|
||||
|
||||
private void averageMultipleMeasurements(String measurementName, Function<Integer, Long> measurement, int range) {
|
||||
double avgTime = IntStream.range(0, 100)
|
||||
.mapToLong(i -> measurement.apply(range))
|
||||
.average()
|
||||
.orElseThrow();
|
||||
|
||||
System.out.println(MessageFormat.format("{0}; Stream size: {1}; Processing Time (ms): {2}", measurementName, range, avgTime));
|
||||
}
|
||||
|
||||
public long measureTimeForMultipleFilters(int range) {
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start();
|
||||
|
||||
IntStream.range(0, range)
|
||||
.boxed()
|
||||
.filter(i -> i != 10)
|
||||
.filter(i -> i != 20)
|
||||
.filter(i -> i != 30)
|
||||
.filter(i -> i != 40)
|
||||
.filter(i -> i != 50)
|
||||
.filter(i -> i != 60)
|
||||
.count();
|
||||
|
||||
watch.stop();
|
||||
return watch.getTime();
|
||||
}
|
||||
|
||||
public long measureTimeForParallelStreamWithMultipleFilters(int range) {
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start();
|
||||
|
||||
IntStream.range(0, range)
|
||||
.boxed()
|
||||
.parallel()
|
||||
.filter(i -> i != 10)
|
||||
.filter(i -> i != 20)
|
||||
.filter(i -> i != 30)
|
||||
.filter(i -> i != 40)
|
||||
.filter(i -> i != 50)
|
||||
.filter(i -> i != 60)
|
||||
.count();
|
||||
|
||||
watch.stop();
|
||||
return watch.getTime();
|
||||
}
|
||||
|
||||
public long measureTimeForComplexCondition(int range) {
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start();
|
||||
|
||||
IntStream.range(0, range)
|
||||
.boxed()
|
||||
.filter(i -> i != 10 && i != 20 && i != 30 && i != 40 && i != 50 && i != 60)
|
||||
.count();
|
||||
|
||||
watch.stop();
|
||||
return watch.getTime();
|
||||
}
|
||||
|
||||
public long measureTimeForParallelStreamWithComplexCondition(int range) {
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start();
|
||||
|
||||
IntStream.range(0, range)
|
||||
.boxed()
|
||||
.parallel()
|
||||
.filter(i -> i != 10 && i != 20 && i != 30 && i != 40 && i != 50 && i != 60)
|
||||
.count();
|
||||
|
||||
watch.stop();
|
||||
return watch.getTime();
|
||||
}
|
||||
|
||||
public long measureTimeForOlfForLoopWithComplexCondition(int range) {
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start();
|
||||
|
||||
int count = 0;
|
||||
for (int i = 0; i <= range; i++) {
|
||||
if (i != 10 && i != 20 && i != 30 && i != 40 && i != 50 && i != 60) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
watch.stop();
|
||||
return watch.getTime();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.baeldung.streams.multiplefilters;
|
||||
|
||||
import static java.util.function.Predicate.not;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MultipleFiltersVsComplexConditionReadabilityUnitTest {
|
||||
|
||||
private List<Student> students;
|
||||
private Student mathStudent;
|
||||
|
||||
@Before
|
||||
public void beforeEach() {
|
||||
this.mathStudent = new Student();
|
||||
mathStudent.setName("John Doe");
|
||||
mathStudent.setYear(3);
|
||||
mathStudent.setProfile(Student.Profile.MATH);
|
||||
mathStudent.setMarks(List.of(80, 90, 77, 95, 100));
|
||||
|
||||
Student csStudent = new Student();
|
||||
csStudent.setName("Paul Atreides");
|
||||
csStudent.setYear(2);
|
||||
csStudent.setProfile(Student.Profile.COMPUTER_SCIENCE);
|
||||
csStudent.setMarks(List.of(30, 40, 60));
|
||||
|
||||
this.students = List.of(mathStudent, csStudent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingMultipleFilters_dataShouldBeFiltered() {
|
||||
List<Student> filteredStream = students.stream()
|
||||
.filter(s -> s.getMarksAverage() > 50)
|
||||
.filter(s -> s.getMarks().size() > 3)
|
||||
.filter(not(s -> s.getProfile() == Student.Profile.PHYSICS))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(filteredStream).containsExactly(mathStudent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingSingleComplexFilter_dataShouldBeFiltered() {
|
||||
List<Student> filteredStream = students.stream()
|
||||
.filter(s -> s.getMarksAverage() > 50
|
||||
&& s.getMarks().size() > 3
|
||||
&& s.getProfile() != Student.Profile.PHYSICS)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(filteredStream).containsExactly(mathStudent);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUsingSingleComplexFilterExtracted_dataShouldBeFiltered() {
|
||||
List<Student> filteredStream = students.stream()
|
||||
.filter(Student::isEligibleForScholarship)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
assertThat(filteredStream).containsExactly(mathStudent);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package com.baeldung.streams.multiplefilters;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Student {
|
||||
|
||||
private String name;
|
||||
private int year;
|
||||
private List<Integer> marks;
|
||||
private Profile profile;
|
||||
|
||||
public enum Profile {
|
||||
COMPUTER_SCIENCE,
|
||||
MATH,
|
||||
PHYSICS
|
||||
}
|
||||
|
||||
public double getMarksAverage() {
|
||||
return marks.stream().collect(Collectors.averagingInt(m -> m));
|
||||
}
|
||||
|
||||
public boolean isEligibleForScholarship() {
|
||||
return getMarksAverage() > 50
|
||||
&& marks.size() > 3
|
||||
&& profile != Profile.PHYSICS;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public void setYear(int year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public List<Integer> getMarks() {
|
||||
return marks;
|
||||
}
|
||||
|
||||
public void setMarks(List<Integer> marks) {
|
||||
this.marks = marks;
|
||||
}
|
||||
|
||||
public Profile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
public void setProfile(Profile profile) {
|
||||
this.profile = profile;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue