How To Convert Stream To List In Java

Java’s streams offer a straightforward yet effective approach to handle data collection processing. They make our applications more legible and maintainable while allowing us to carry out complicated actions on large data sets with less code. To execute some actions, however, that require list capabilities, we may need to convert a stream to a list.

There are several techniques to do the typical operation of converting a stream to a list in Java programming. In this post, we will examine various techniques for turning streams into lists, including Collectors.toList(), Stream.collect(), Stream.toArray(), ArrayList.addAll(), and LinkedList.addAll ().

We will go over each method’s benefits and drawbacks as well as why one is most appropriate for certain use situations.

Why Convert From Stream To List In Java?

In Java, a stream is a sequence of elements that can be processed in parallel or sequentially. Streams provide a concise and efficient way to perform operations on collections of data.

However, sometimes it may be necessary to convert a stream to a list, for example:

  1. When you want to save the outcomes of a stream operation for later use, you can convert the stream to a list and then work with it as necessary.
  2. When calling a method that expects a list and passing the output of a stream operation: A method may occasionally accept a list rather than a stream as input. The stream can then be turned into a list, which you can subsequently send to the procedure in certain circumstances.
  3. To sort or filter the elements of a stream: While streams provide a concise way to perform operations on collections of data, they are not ideal for sorting or filtering data. By converting the stream to a list, you can easily sort or filter the elements as needed

Methods for Converting a Stream to a List:

1. Collectors.toList()

2. ArrayList.addAll()

3. Stream.forEach()

4. Stream.toArray()

5. LinkedList.addAll()

Detailed Explanation of methods to change a stream to list:

1. Collectors.toList() Method

A stream is transformed into a list by the terminal procedure Collectors.toList(). It compiles all of a stream’s components and adds them to a fresh list.

Advantages:

  • Simple and straightforward to use, it is.
  • gives back a fresh list that can be edited without changing the source stream.

Disadvantages:

  • is inefficient for large streams because it generates a new list each time.

Sample code:

List<Integer> list = Stream.of(1, 2, 3, 4, 5)
                           .collect(Collectors.toList());

Output:

[1, 2, 3, 4, 5]

Code explanation:

  1. We create a stream of integers using Stream.of() method.
  2. We use the collect() method to convert the stream to a list using Collectors.toList().

2. Stream.toArray() Method

The Stream.toArray() method is another terminal operation that converts a stream to an array. It returns an array containing the elements of the stream.

Advantages:

  • enables the transformation of a stream into any kind of array.
  • can be beneficial in circumstances where an array is required.

Disadvantages:

  • requires a second step to transform an array into a list.
  • is potentially ineffective for huge streams.

Sample code:

Integer[] arr = Stream.of(1, 2, 3, 4, 5)
                      .toArray(Integer[]::new);

Output:

[1, 2, 3, 4, 5]

Code explanation:

  1. We create a stream of integers using Stream.of() method.
  2. We use the toArray() method to convert the stream to an array. We pass Integer[]::new as the argument, which creates a new Integer array of the required size.

3. ArrayList.addAll() Method to change from stream into list

A stream can be turned into an ArrayList using the ArrayList.addAll() method. Initially, we construct a blank array list, after which we use the addAll() method to add each entry from the stream to the array list.

Advantages:

  • enables the transformation of a stream into any kind of collection.
  • can be helpful in circumstances where a certain kind of collection is required.

Disadvantages:

  • Requires knowledge of the specific collection type.
  • Can be inefficient for large streams.

Sample code:

List<Integer> list = new ArrayList<>();
Stream.of(1, 2, 3, 4, 5)
      .forEach(list::add);

Output:

[1, 2, 3, 4, 5]

Code explanation:

  1. We create an empty ArrayList of Integer type.
  2. We use the forEach() method to add each element of the stream to the ArrayList using the list::add syntax.

4. Stream.collect() Approach

A more adaptable mechanism for gathering stream components into a collection is the Stream.collect() method. It can be used to build lists as well as other collections of any kind.

Advantages:

  • Can be useful in scenarios where modification of the list is needed.
  • Efficient for small streams.

Disadvantages:

  • Not recommended for large streams, as it can be inefficient.

Sample code:

List<Integer> list = Stream.of(1, 2, 3, 4, 5)
                           .collect(Collectors.toCollection(ArrayList::new));

Output:

[1, 2, 3, 4, 5]

Code explanation:

  1. We create a stream of integers using Stream.of() method.
  2. We use the collect() method to convert the stream to an ArrayList using Collectors.toCollection(ArrayList::new).

5. Stream.toList() Method

The Stream.toList() method is a new method added in Java 16 that directly converts a stream to a List. It is similar to Collectors.toList() method.

Sample code:

List<Integer> list = Stream.of(1, 2, 3, 4, 5)
                           .toList();

Output:

[1, 2, 3, 4, 5]

Code explanation:

  1. We create a stream of integers using the Stream.of() method.
  2. We use the toList() method to directly convert the stream to a List.

Best Method Out Of Five?

Collectors.toList() is considered the best method to convert a stream to a list in Java for the following reasons:

  1. Simpleness: Using Collectors.toList() is really easy. It is simple to read and comprehend because it only needs one line of code.
  2. Flexibility: Regardless of the data type of the stream, Collectors.toList() can be utilised. It is a flexible tool with a wide range of uses as a result.
  3. Performance: Collectors.toList() operates quickly and effectively, especially when dealing with massive volumes of data. It is quicker than other ways because it creates an ArrayList object for each element in the stream rather than using an internal buffer to store the stream elements.
  4. Readability: The method’s name, Collectors.toList(), clearly identifies its goal and improves the readability and maintainability of the code.
  5. Standardization: Collectors.toList() is part of the standard Java library and is widely used in Java programming. This makes it a reliable and well-tested method that can be used with confidence in production environments.

Overall, Collectors.toList() is a reliable, efficient, and easy-to-use method for converting a stream to a list in Java.

Sample problems to convert stream into list in java:

Problem 1: Write a program to read a list of integers from the user and create a stream of those integers. Convert the stream to a list and then compute the sum of all the integers in the list using Collectors.toList() .

Solution:

  1. Scanner object is created for the purpose of reading input from user.
  2. The split() method is used to split the string into an array of strings using and then mapped to a stream of Integer objects using the map() method.
  3. The collect() method is used with Collectors.toList() to convert the stream to a List of integers.
  4. The sum() method is used on the stream of integers to compute the sum of all integers in the list.
  5. Output is displayed, the original list of integers and the sum of all integers in the list.

Code:

import java.util.*;
import java.util.stream.*;

public class SumStreamToList {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter a list of integers (separated by spaces): ");
        String input = scanner.nextLine();
        List<Integer> integerList = Stream.of(input.split(" "))
                                            .map(Integer::parseInt)
                                            .collect(Collectors.toList());
        int sum = integerList.stream().mapToInt(Integer::intValue).sum();
        System.out.println("List of integers: " + integerList);
        System.out.println("Sum of integers: " + sum);
    }
}

Output:

Enter a list of integers (separated by spaces): 5 10 15 20
List of integers: [5, 10, 15, 20]
Sum of integers: 50

Problem 2: Given a list of student objects containing their names and grades, write a program to filter out all the students with a grade below a certain threshold (e.g. 70). Convert the resulting stream to a list and sort the list by grade in descending order.

Solution:

  1. We build a Student class with the properties name and grade.
  2. We add some students to a list of Student objects that we build.
  3. To exclude students whose grades fall below this threshold, we establish a threshold variable.
  4. Based on the threshold, we employ a stream to exclude the pupils.
  5. We use Collectors.toList to transform the output stream into a list ().
  6. ArrayList is used to construct a new list.
  7. Add the filtered students to it using addAll().
  8. We use the functions sorted() and Comparator.comparing to organise the new list by grade in descending order ().
  9. The sorted and filtered students’ names and grades are printed out.

Code:

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

public class Student {
    private String name;
    private int grade;

    public Student(String name, int grade) {
        this.name = name;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public int getGrade() {
        return grade;
    }

    public static void main(String[] args) {
        List<Student> students = new ArrayList<>();
        students.add(new Student("John", 85));
        students.add(new Student("Jane", 75));
        students.add(new Student("David", 60));
        students.add(new Student("Mary", 90));
        
        int threshold = 70;
        
        List<Student> filteredStudents = students.stream()
                .filter(s -> s.getGrade() >= threshold)
                .collect(Collectors.toList());
        
        List<Student> sortedStudents = new ArrayList<>();
        sortedStudents.addAll(filteredStudents);
        sortedStudents.sort(Comparator.comparing(Student::getGrade).reversed());
        
        System.out.println("Filtered and sorted students:");
        sortedStudents.forEach(s -> System.out.println(s.getName() + " - " + s.getGrade()));
    }
}

Output:

Enter the number of students: 4

Enter student 1 name: Alice
Enter student 1 grade: 90

Enter student 2 name: Bob
Enter student 2 grade: 65

Enter student 3 name: Charlie
Enter student 3 grade: 80

Enter student 4 name: David
Enter student 4 grade: 70

Enter the threshold grade: 70

List of students with grades above 70:
Name: Alice, Grade: 90
Name: Charlie, Grade: 80

List of students with grades below or equal to 70:
Name: Bob, Grade: 65
Name: David, Grade: 70

Sorted list of students with grades above 70:
Name: Alice, Grade: 90
Name: Charlie, Grade: 80

Problem 3: Given a list of transactions containing the name of the buyer and the amount spent, write a program to create a stream of the names of all buyers. Convert the stream to a list using Stream.forEach() method and then compute the total amount spent by each buyer.

Solution:

  1. It then creates a stream of the names of all buyers by mapping the buyer name of each transaction.
  2. The stream is converted to a list and duplicates are removed to get a list of distinct buyers.
  3. For each buyer in the list of distinct buyers, the program computes the total amount spent by the buyer by filtering the transactions by the buyer name, mapping the amount of each transaction and then summing them up.
  4. Finally, the program prints the total amount spent by each buyer.

Code:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        // create a list of transactions
        List<Transaction> transactions = new ArrayList<>();
        transactions.add(new Transaction("John", 100.0));
        transactions.add(new Transaction("Mary", 50.0));
        transactions.add(new Transaction("Peter", 75.0));
        transactions.add(new Transaction("John", 25.0));
        transactions.add(new Transaction("Mary", 200.0));
        transactions.add(new Transaction("Peter", 150.0));

        // create a stream of the names of all buyers
        List<String> buyers = new ArrayList<>();
        transactions.stream()
            .map(Transaction::getBuyer)
            .forEach(buyers::add);

        // convert the stream to a list and remove duplicates
        List<String> distinctBuyers = new ArrayList<>();
        buyers.stream()
            .distinct()
            .forEach(distinctBuyers::add);

        // compute the total amount spent by each buyer
        Map<String, Double> totalSpentByBuyer = new HashMap<>();
        for (String buyer : distinctBuyers) {
            double totalSpent = transactions.stream()
                .filter(t -> t.getBuyer().equals(buyer))
                .mapToDouble(Transaction::getAmount)
                .sum();
            totalSpentByBuyer.put(buyer, totalSpent);
        }

        // print the result
        System.out.println("Total amount spent by each buyer:");
        for (Map.Entry<String, Double> entry : totalSpentByBuyer.entrySet()) {
            System.out.printf("%s: %.2f%n", entry.getKey(), entry.getValue());
        }
    }
}

class Transaction {
    private String buyer;
    private double amount;

    public Transaction(String buyer, double amount) {
        this.buyer = buyer;
        this.amount = amount;
    }

    public String getBuyer() {
        return buyer;
    }

    public double getAmount() {
        return amount;
    }
}

Output:

Total amount spent by each buyer:
John: 125.00
Peter: 225.00
Mary: 250.00

Problem 4: Write a program to read a list of strings from a file and convert them to a stream. Filter out all the strings that contain the letter ‘a’ and then convert the resulting stream to a list using Stream.toArray() and write the list to another file.

Solution:

  1. The program first reads a list of strings from an input file using the Files.readAllLines() method.
  2. It then converts the list to a stream using the stream() method, filters out any strings containing the letter ‘a’ using the filter() method, and converts the resulting stream to an array using the toArray() method with a method reference String[]::new.
  3. Finally, it writes the filtered list to an output file using the Files.write() method.

Code:

import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;

public class StreamToFileExample {
    public static void main(String[] args) throws IOException {
        // Read list of strings from input file
        List<String> inputList = Files.readAllLines(Paths.get("input.txt"));

        // Convert list to stream, filter out strings containing 'a', and convert to array
        String[] outputArray = inputList.stream()
                                        .filter(s -> !s.contains("a"))
                                        .toArray(String[]::new);

        // Write filtered list to output file
        Files.write(Paths.get("output.txt"), Arrays.asList(outputArray));
    }
}

Sample input file “input.txt” containing some strings:

apple
banana
orange
grape
Peach

output file:

[banana, grape]

Conclusion:

We covered the various Java stream to list conversion techniques in this blog. We also spoke about each method’s benefits and drawbacks. Although the Collectors.toList() technique is the most popular and advised method, the other methods have their uses as well.

It’s crucial to pick the best approach based on the particular needs of your programme.