Streams are a sequence of elements supporting sequential and parallel aggregate operations. They provide a high-level abstraction for processing collections of data in a functional style.
// From collections
List<String> list = Arrays.asList("a", "b", "c");
Stream<String> stream = list.stream();
// From arrays
String[] array = {"a", "b", "c"};
Stream<String> streamFromArray = Arrays.stream(array);
// Using Stream.of()
Stream<String> streamOf = Stream.of("a", "b", "c");
// Infinite streams
Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 2);
Stream<Double> randomNumbers = Stream.generate(Math::random);
Filter elements based on a predicate condition.
@Test
public void testFilterOperation() {
List<User> users = getUserList();
List<User> activeUsers = users.stream()
.filter(User::isActive)
.filter(user -> user.getAge() > 18)
.collect(Collectors.toList());
assertTrue("Should have active adult users", !activeUsers.isEmpty());
}
Transform elements from one type to another.
@Test
public void testMapOperation() {
List<User> users = getUserList();
List<String> userEmails = users.stream()
.map(User::getEmail)
.collect(Collectors.toList());
List<String> upperCaseNames = users.stream()
.map(User::getName)
.map(String::toUpperCase)
.collect(Collectors.toList());
assertEquals(users.size(), userEmails.size());
}
Flatten nested structures into a single stream.
@Test
public void testFlatMapOperation() {
List<Department> departments = getDepartments();
List<User> allUsers = departments.stream()
.flatMap(dept -> dept.getUsers().stream())
.collect(Collectors.toList());
List<String> allSkills = departments.stream()
.flatMap(dept -> dept.getUsers().stream())
.flatMap(user -> user.getSkills().stream())
.distinct()
.collect(Collectors.toList());
assertTrue("Should have users from all departments", !allUsers.isEmpty());
}
Collect stream elements into various data structures.
@Test
public void testCollectOperations() {
List<User> users = getUserList();
// Collect to List
List<String> names = users.stream()
.map(User::getName)
.collect(Collectors.toList());
// Collect to Set
Set<String> uniqueRoles = users.stream()
.map(User::getRole)
.collect(Collectors.toSet());
// Collect to Map
Map<String, User> userMap = users.stream()
.collect(Collectors.toMap(User::getEmail, user -> user));
// Group by role
Map<String, List<User>> usersByRole = users.stream()
.collect(Collectors.groupingBy(User::getRole));
assertFalse("Should have user names", names.isEmpty());
assertFalse("Should have unique roles", uniqueRoles.isEmpty());
}
Combine stream elements into a single result.
@Test
public void testReduceOperations() {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Sum using reduce
Optional<Integer> sum = numbers.stream()
.reduce((a, b) -> a + b);
// Sum with identity
Integer sumWithIdentity = numbers.stream()
.reduce(0, (a, b) -> a + b);
// Find maximum
Optional<Integer> max = numbers.stream()
.reduce(Integer::max);
assertEquals(15, sumWithIdentity.intValue());
assertTrue("Sum should be present", sum.isPresent());
assertEquals(15, sum.get().intValue());
}
Parallel streams can improve performance for CPU-intensive operations on large datasets.
@Test
public void testParallelStreams() {
List<Integer> largeList = IntStream.rangeClosed(1, 1000000)
.boxed()
.collect(Collectors.toList());
// Sequential processing
long startTime = System.currentTimeMillis();
long sequentialSum = largeList.stream()
.mapToLong(Integer::longValue)
.sum();
long sequentialTime = System.currentTimeMillis() - startTime;
// Parallel processing
startTime = System.currentTimeMillis();
long parallelSum = largeList.parallelStream()
.mapToLong(Integer::longValue)
.sum();
long parallelTime = System.currentTimeMillis() - startTime;
assertEquals(sequentialSum, parallelSum);
System.out.println("Sequential time: " + sequentialTime + "ms");
System.out.println("Parallel time: " + parallelTime + "ms");
}
@Test
public void testDataProcessing() {
List<TestResult> testResults = getTestResults();
// Calculate pass rate
double passRate = testResults.stream()
.mapToDouble(result -> result.isPassed() ? 1.0 : 0.0)
.average()
.orElse(0.0);
// Find failed tests
List<String> failedTests = testResults.stream()
.filter(result -> !result.isPassed())
.map(TestResult::getTestName)
.collect(Collectors.toList());
// Group by test suite
Map<String, List<TestResult>> resultsBySuite = testResults.stream()
.collect(Collectors.groupingBy(TestResult::getSuiteName));
assertTrue("Pass rate should be above 80%", passRate > 0.8);
System.out.println("Failed tests: " + failedTests);
}
@Test
public void testWebElementProcessing() {
List<WebElement> elements = driver.findElements(By.className("test-item"));
// Find visible elements
List<WebElement> visibleElements = elements.stream()
.filter(WebElement::isDisplayed)
.collect(Collectors.toList());
// Get all text content
List<String> textContents = elements.stream()
.filter(WebElement::isDisplayed)
.map(WebElement::getText)
.filter(text -> !text.isEmpty())
.collect(Collectors.toList());
// Check if any element contains specific text
boolean hasExpectedText = elements.stream()
.anyMatch(element -> element.getText().contains("Expected Text"));
assertFalse("Should have visible elements", visibleElements.isEmpty());
assertTrue("Should contain expected text", hasExpectedText);
}