How to Sort and Filter Collections in Java Using Streams
Java Streams API is a powerful tool introduced in Java 8 that allows developers to process collections and streams of data in a declarative and functional style. By using Streams, you can sort, filter, map, and reduce collections with minimal and clean code.
In this guide, we will explore:
- How to sort collections using Streams.
- How to filter data from Lists, Sets, and Maps efficiently.
- Practical examples and best practices for using Streams in real-world applications.
📖 Learn more: Oracle Documentation – Java Streams
What are Streams in Java?
A Stream is a sequence of elements that supports sequential and parallel operations on collections. Streams allow functional-style operations on elements, such as filtering, mapping, sorting, and collecting.
Key Characteristics of Streams:
- Not a data structure: Streams do not store data, but process data from sources such as Collections, Arrays, I/O channels, and Generators.
- Functional operations: Streams support map, filter, reduce, collect, sort, and more.
- Lazy evaluation: Intermediate operations are not executed until a terminal operation is called.
- Parallel processing: Streams can handle data concurrently using parallelStream().
📖 Read more: Baeldung – Java Streams
How to Sort Collections Using Streams
1. Sorting Lists with Streams
Sorting a List of Strings or Objects is straightforward using Streams.
Example: Sorting a List of Strings
import java.util.Arrays;
import java.util.List;
public class SortExample {
public static void main(String[] args) {
List<String> fruits = Arrays.asList("Banana", "Apple", "Cherry", "Date");
// Sorting alphabetically
fruits.stream()
.sorted()
.forEach(System.out::println);
// Sorting in reverse order
fruits.stream()
.sorted((a, b) -> b.compareTo(a))
.forEach(System.out::println);
}
}
2. Sorting Objects with Custom Comparator
You can sort objects using a custom comparator by specifying attributes for sorting.
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return name + " - " + age;
}
}
public class SortObjectsExample {
public static void main(String[] args) {
List<Person> people = new ArrayList<>();
people.add(new Person("Alice", 30));
people.add(new Person("Bob", 25));
people.add(new Person("Charlie", 35));
// Sort by age
people.stream()
.sorted(Comparator.comparingInt(p -> p.age))
.forEach(System.out::println);
}
}
How to Filter Collections Using Streams
1. Filtering Elements from a List
The filter() method allows you to select elements based on a predicate condition.
Example: Filtering Even Numbers
import java.util.Arrays;
import java.util.List;
public class FilterExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
}
}
2. Filtering a Map Using Streams
You can filter a Map by keys or values using Streams.
import java.util.HashMap;
import java.util.Map;
public class FilterMapExample {
public static void main(String[] args) {
Map<String, Integer> items = new HashMap<>();
items.put("Apple", 50);
items.put("Banana", 30);
items.put("Cherry", 20);
items.put("Date", 10);
// Filter items with value greater than 20
items.entrySet().stream()
.filter(entry -> entry.getValue() > 20)
.forEach(System.out::println);
}
}
📖 Read more: GeeksforGeeks – Filtering Collections in Java
Best Practices for Using Streams in Java
- Prefer Streams for Bulk Operations: When processing large datasets, Streams offer efficient and readable code.
- Use Parallel Streams Cautiously: While parallelStream() can improve performance, avoid it for stateful operations or shared mutable data.
- Avoid Side-Effects: Operations within Streams should be stateless and non-interfering.
- Combine Operations: Chain map(), filter(), sorted(), and collect() for concise code.
- Use Collectors for Complex Results: The Collectors class offers methods for grouping, partitioning, and reducing data.
Frequently Asked Questions (FAQ)
1. What is the difference between sorted() and filter() in Java Streams?
- sorted() is used to order elements in a Stream.
- filter() is used to select elements that meet a condition.
2. Can I sort a Set using Streams in Java?
Yes, you can sort a Set by converting it to a Stream, applying sorted(), and collecting it back to a Set or List.
Set<String> sortedSet = mySet.stream().sorted().collect(Collectors.toSet());
3. How do I convert a filtered stream to a List in Java?
Use Collectors.toList() to collect the Stream results into a List:
List<String> filteredList = myList.stream().filter(condition).collect(Collectors.toList());
4. What is the advantage of using Streams over traditional loops?
Streams provide concise syntax, parallel processing capabilities, and functional programming benefits, reducing the risk of errors.
5. Can I use Streams with Arrays in Java?
Yes, use Arrays.stream(array) or Stream.of(array) to convert arrays to streams.
📖 Learn more: Programiz – Java Streams
Conclusion
By leveraging Java Streams, you can sort and filter collections efficiently and write concise, maintainable code. Mastering Streams opens up opportunities for functional programming and parallel data processing in Java.
🚀 Now that we know how to manipulate data, let’s learn how to connect Java to a database!