So, you're here to learn about Streams in Java, but not the kind of streams where people go fishing or water flows. We're talking about data streams, a powerful feature introduced in Java 8 that makes working with data a whole lot easier. Whether you're brand new to this or you've tried it but couldn’t quite crack it, don’t worry. I’ll walk you through the entire journey in plain, easy-to-understand language.
Ready? Let’s dive into Java Streams!
A Stream is a way to process data in a sequence. Imagine you have a list of items, and you want to do something with those items (filter, sort, map, etc.). A Stream lets you do all that in a clean and efficient way. It’s like an assembly line where your data flows through different steps until it gets processed.
Key things to remember about streams:
Why not just use a for loop or manipulate collections directly? Well, there are three main reasons:
Let’s take a look at the two main types of stream operations: Intermediate and Terminal.
These are the operations that prepare the data but don’t produce a final result right away. Think of these as the “workshop” steps.
filter()
This is like a sieve. It picks out elements based on a condition. For example, if you want only the even numbers from a list of integers, you'd use filter().
java Copy code Listnumbers = Arrays.asList(1, 2, 3, 4, 5); List evenNumbers = numbers.stream() .filter(n -> n % 2 == 0) .collect(Collectors.toList()); // Output: [2, 4]
Why filter? Without filter(), you'd need to manually loop through the list and add only the matching elements to a new list. filter() lets you do this in one clean step.
map()
This is a transformer. It takes an element and returns something different. For example, if you have a list of strings and you want the lengths of each string:
java Copy code Listwords = Arrays.asList("apple", "banana", "cherry"); List lengths = words.stream() .map(String::length) .collect(Collectors.toList()); // Output: [5, 6, 6]
Why map? map() is used when you need to transform each element into something else, like converting a list of strings to a list of their lengths.
distinct()
It’s like a duplicate filter. This removes duplicate elements from a stream.
java Copy code Listnumbers = Arrays.asList(1, 2, 2, 3, 4, 4, 5); List distinctNumbers = numbers.stream() .distinct() .collect(Collectors.toList()); // Output: [1, 2, 3, 4, 5]
Why distinct? In a normal list, you’d need to manually check for duplicates. distinct() does this for you in one line.
sorted()
This sorts your data in natural order (or a custom one, if you like).
java Copy code Listnames = Arrays.asList("Charlie", "Alice", "Bob"); List sortedNames = names.stream() .sorted() .collect(Collectors.toList()); // Output: ["Alice", "Bob", "Charlie"]
Why sorted? Instead of writing sorting logic yourself, sorted() handles it for you.
These are the ones that produce the final result, and they trigger the processing of the entire stream. Think of these as the "exit point."
collect()
This is the most common terminal operation. It gathers the results of the stream and puts them into a List, Set, or other collection.
java Copy code Listnames = Arrays.asList("Charlie", "Alice", "Bob"); List upperNames = names.stream() .map(String::toUpperCase) .collect(Collectors.toList()); // Output: ["CHARLIE", "ALICE", "BOB"]
Why collect? You’ll almost always use collect() to gather the results of your stream into a collection. It's your final stop.
forEach()
If you don’t need a result and just want to perform an action on each item (like printing them), forEach() is your friend.
java Copy code numbers.stream() .forEach(System.out::println);
Why forEach? This is perfect for side-effects, like printing data to the console or writing to a file.
reduce()
reduce() takes a bunch of data and boils it down to a single result. For example, summing a list of numbers:
java Copy code int sum = numbers.stream() .reduce(0, Integer::sum); // Output: 15
Why reduce? When you need to combine or accumulate values into a single result, reduce() is your go-to.
Not all streams are created from collections. Java provides other types of streams to handle various kinds of data:
IntStream, LongStream, DoubleStream
These streams are specialized for dealing with primitive types. Instead of boxing and unboxing values like Stream
Example:
java Copy code IntStream intStream = IntStream.of(1, 2, 3, 4); int sum = intStream.sum(); // Output: 10
Stream of Files
You can create streams from files using Files.lines().
java Copy code try (Streamlines = Files.lines(Paths.get("data.txt"))) { lines.forEach(System.out::println); } catch (IOException e) { e.printStackTrace(); }
Why use file streams? When dealing with large files, loading all data into memory may not be efficient. Using a stream allows you to process it line by line.
Good question! Let’s compare:
Streams in Java are all about simplifying the way you process data. They make your code more readable, easier to maintain, and more efficient when working with collections. Whether you're filtering, transforming, or reducing data, Streams have you covered with clear, straightforward methods that eliminate the need for bulky loops and manual work.
Now that you're well-equipped with the basics of Streams, why stop here? Follow me on Twitter, LinkedIn, or check out my blog for more Java tips that’ll make you a pro in no time! And if you found this guide helpful, share it with your fellow developers—because sharing is caring!
Ready to try it out? Let’s get that Stream flowing in your next project!
Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.
Copyright© 2022 湘ICP备2022001581号-3