Java Stream API

Java 8 introduces a fresh package known as java.util.stream, offering a variety of classes, interfaces, and enums for performing functional-style actions on elements. To leverage streams, the java.util.stream package needs to be imported.

Stream provides following features:

  • Stream does not store elements. It simply conveys elements from a source such as a data structure, an array, or an I/O channel, through a pipeline of computational operations.
  • Stream is functional in nature. Operations performed on a stream does not modify it's source. For example, filtering a Stream obtained from a collection produces a new Stream without the filtered elements, rather than removing elements from the source collection.
  • Stream is lazy and evaluates code only when required.
  • The elements of a stream are only visited once during the life of a stream. Like an Iterator, a new stream must be generated to revisit the same elements of the source.

Streams in Java can be utilized for operations like filtering, collecting, printing, and transforming data structures. Below are instances demonstrating the application of different operations using streams.

Various Core Operations Over Streams

1. Intermediate Operations

In Java Streams, intermediate operations produce a new Stream and are commonly employed to modify or sift through the elements of the initial Stream. These operations are deferred, indicating that they do not execute any actions until a terminal operation is invoked, allowing for the chaining of multiple intermediate operations.

Common Intermediate Operations:

  • map(Function<T, R>): Transforms each element of the Stream into another form using the provided function.
  • filter(Predicate<T>): Selects elements from the Stream based on a specified condition.
  • flatMap(Function<T, Stream<R>>): Transforms each element into zero or more elements by applying a function that returns a stream for each element.
  • distinct: Removes duplicate elements from the Stream.
  • sorted: Sorts the elements of the Stream.
  • limit(long n): Truncates the Stream to be no longer than the specified size.
  • skip(long n): Skips the first n elements of the Stream.
  • peek(Consumer<T>): Performs a specified action on each element of the Stream without consuming the elements.
  • 2. Terminal Operations

Operations that are considered terminal in streams are the ones that utilize the stream and generate an outcome, which could be a value, a set of data, or an action. When a terminal operation is executed, the stream is handled entirely and becomes ineligible for further use.

Common Terminal Operations:

  • forEach(Consumer<T>): Acts as each element of the Stream.
  • collect(Collector<T, A, R>): Reduces the elements of the Stream into a mutable result container, such as a list or a map.
  • reduce(BinaryOperator<T>): Reduces the elements of the Stream to a single value using an associative accumulation function.
  • count: Returns the count of elements in the Stream.
  • anyMatch(Predicate<T>): Returns true if any element of the Stream matches the given predicate.
  • allMatch(Predicate<T>): Returns true if all elements of the Stream match the given predicate.
  • noneMatch(Predicate<T>): Returns true if no elements of the Stream match the given predicate.
  • findFirst: Returns an Optional describing the first element of the Stream, or an empty Optional if the Stream is empty.
  • findAny: Returns an Optional describing some element of the Stream, or an empty Optional if the Stream is empty.
  • 3. Short-Circuit Operations

Short-circuit operations represent a category of terminal operations that do not require processing the complete Stream in order to generate an output. These operations enable an early termination from the stream processing sequence, which can lead to saved computational resources and time.

Common Short-Circuit Operations:

  • anyMatch(Predicate<T>): Stops processing and returns true if any element matches the given predicate.
  • allMatch(Predicate<T>): Stops processing and returns false if any element does not match the given predicate.
  • noneMatch(Predicate<T>): Stops processing and returns true if no elements match the given predicate.
  • findFirst: Returns the first element encountered in the Stream and then stops processing.
  • findAny: Returns any element encountered in the Stream and then stops processing.
  • Java Stream Interface Methods

Methods Description
boolean allMatch(Predicate<? super T> predicate) It returns all elements of this stream which match the provided predicate. If the stream is empty then true is returned and the predicate is not evaluated.
boolean anyMatch(Predicate<? super T> predicate) It returns any element of this stream that matches the provided predicate. If the stream is empty then false is returned and the predicate is not evaluated.
static static <T> Stream.Builder<T> builder() Stream.BuilderStream builder() It returns a builder for a Stream.
<R> R collect(Collector<Collector> collector) It performs a mutable reduction operation on the elements of this stream using a Collector. A Collector encapsulates the functions used as arguments to collect(Supplier, BiConsumer, BiConsumer), allowing for reuse of collection strategies and composition of collect operations such as multiple-level grouping or partitioning.
<a> R collect(Supplier<Supplier<R>> supplier, BiConsumerBiConsumer<T, A> accumulator, BiConsumerBiConsumer<T, T> combiner) It performs a mutable reduction operation on the elements of this stream. A mutable reduction is one in which the reduced value is a mutable result container, such as an ArrayList, and elements are incorporated by updating the state of the result rather than by replacing the result.
static static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) StreamStream concat(StreamStream<T> a, StreamStream<T> b) It creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. The resulting stream is ordered if both of the input streams are ordered, and parallel if either of the input streams is parallel. When the resulting stream is closed, the close handlers for both input streams are invoked.
long count() It returns the count of elements in this stream. This is a special case of a reduction.
Stream<T> distinct() It returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.
static static <T> Stream<T> empty() StreamStream<T> empty() It returns an empty sequential Stream.
StreamStream<T> filter(Predicate<? super T> predicate) filter(PredicatePredicate<T> predicate) It returns a stream consisting of the elements of this stream that match the given predicate.
Optional<T> findAny() It returns an Optional describing some element of the stream, or an empty Optional if the stream is empty.
Optional<T> findFirst() It returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty. If the stream has no encounter order, then any element may be returned.
Stream<T> flatMap(Function<? super T,? extends Stream<? extends R>> mapper) It returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function StreamStream<T> flatMap(FunctionFunction<? super T,? extends Stream<? extends R>>> mapper) It returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)
DoubleStream flatMapToDouble(Function<? super T,? extends DoubleStream> mapper) It returns a DoubleStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have placed been into this stream. (If a mapped stream is null an empty stream is used, instead.)
IntStream flatMapToInt(Function<? super T,? extends IntStream> mapper) It returns an IntStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)
LongStream flatMapToLong(Function<? super T,? extends LongStream> mapper) It returns a LongStream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. Each mapped stream is closed after its contents have been placed into this stream. (If a mapped stream is null an empty stream is used, instead.)
void forEach(Consumer<? super T> action) It performs an action for each element of this stream.
void forEachOrdered(Consumer<? super T> action) It performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order.
static static <T> Stream<T> generate(Supplier<T> s) StreamStream generate(SupplierSupplier s) It returns an infinite sequential unordered stream where each element is generated by the provided Supplier. This is suitable for generating constant streams, streams of random elements, etc.
static static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) StreamStream<T> iterate(T seed,UnaryOperatorUnaryOperator<T> f) It returns an infinite sequential ordered Stream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc.
Stream<T> limit(long maxSize) It returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.
<a> Stream<Stream<T>> map(FunctionFunction<? super T> mapper) It returns a stream consisting of the results of applying the given function to the elements of this stream.
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) It returns a DoubleStream consisting of the results of applying the given function to the elements of this stream.
IntStream mapToInt(ToIntFunction<? super T> mapper) It returns an IntStream consisting of the results of applying the given function to the elements of this stream.
LongStream mapToLong(ToLongFunction<? super T> mapper) It returns a LongStream consisting of the results of applying the given function to the elements of this stream.
OptionalOptional <T> max(Comparator<? super T> comparator) max(ComparatorComparator comparator) It returns the maximum element of this stream according to the provided Comparator. This is a special case of a reduction.
OptionalOptional <T> min(Comparator<? super T> comparator) min(ComparatorComparator<? super T> comparator) It returns the minimum element of this stream according to the provided Comparator. This is a special case of a reduction.
boolean noneMatch(Predicate<? super T> predicate) It returns elements of this stream match the provided predicate. If the stream is empty then true is returned and the predicate is not evaluated.
@SafeVarargs static Stream<T> StreamStream of(T... values) It returns a sequential ordered stream whose elements are the specified values.
static static <T> Stream<T> of(T t) StreamStream<T> of(T t) It returns a sequential Stream containing a single element.
StreamStream<T> peek(Consumer<? super T> action) peek(Consumer<Consumer<T>> action) It returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.
OptionalOptional<T> reduce(BinaryOperator<T> accumulator) reduce(BinaryOperatorBinaryOperator<T> accumulator) It performs a reduction on the elements of this stream, using an associative accumulation function, and returns an Optional describing the reduced value, if any.
T reduce(T identity, BinaryOperator<T> accumulator) It performs a reduction on the elements of this stream, using the provided identity value and an associative accumulation function, and returns the reduced value.
<U> U reduce(U identity, BiFunctionBiFunction<T, U, T> accumulator, BinaryOperatorBinaryOperator<T> combiner) It performs a reduction on the elements of this stream, using the provided identity, accumulation and combining functions.
Stream<T> skip(long n) It returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream. If this stream contains fewer than n elements then an empty stream will be returned.
Stream<T> sorted() It returns a stream consisting of the elements of this stream, sorted according to natural order. If the elements of this stream are not Comparable, a java.lang.ClassCastException may be thrown when the terminal operation is executed.
Stream Stream<T> sorted(Comparator<T> comparator) It returns a stream consisting of the elements of this stream, sorted according to the provided Comparator. sorted(ComparatorComparator comparator) It returns a stream consisting of the elements of this stream, sorted according to the provided Comparator.
Object[] toArray() It returns an array containing the elements of this stream.
<T> toArray(IntFunction<T[]> generator) It returns an array containing the elements of this stream, using the provided generator function to allocate the returned array, as well as any additional arrays that might be required for a partitioned execution A[] toArray(IntFunction< T[] > generator) It returns an array containing the elements of this stream, using the provided generator function to allocate the returned array, as well as any additional arrays that might be required for a partitioned execution or for resizing.

Java Example: Filtering Collection without using Stream

In this instance, we will demonstrate data filtering without utilizing streams. This methodology was employed prior to the introduction of the stream package.

Example

Example

import java.util.*;

class Product{

	int id;

	String name;

	float price;

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

}

public class JavaStreamExample {

	public static void main(String[] args) {

		List<Product> productsList = new ArrayList<Product>();

		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		List<Float> productPriceList = new ArrayList<Float>();

		for(Product product: productsList){

			

			// filtering data of list

			if(product.price<30000){

				productPriceList.add(product.price);	// adding price to a productPriceList

			}

		}

		System.out.println(productPriceList);	// displaying data

	}

}

Output:

Output

[25000.0, 28000.0, 28000.0]

Java Stream Example: Filtering Collection by Using Stream

In this scenario, data filtration is being performed utilizing streams, leading to optimized and well-managed code. Streams offer rapid execution capabilities.

Example

Example

import java.util.*;

import java.util.stream.Collectors;

class Product{

	int id;

	String name;

	float price;

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

}

public class JavaStreamExample {

	public static void main(String[] args) {

		List<Product> productsList = new ArrayList<Product>();

		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		List<Float> productPriceList2 =productsList.stream()

					   		         .filter(p -> p.price > 30000)// filtering data

					   		         .map(p->p.price)		// fetching price

					   		         .collect(Collectors.toList());	// collecting as list

		System.out.println(productPriceList2);

	}

}

Output:

Output

[90000.0]

Java Stream Iterating Example

Streams can be utilized for iterating multiple times. They offer built-in functions to handle the operations we specify. In the upcoming demonstration, we will iterate, apply a filter, and set a maximum limit for the iteration.

Example

Example

import java.util.stream.*;

public class JavaStreamExample {

	public static void main(String[] args){

		Stream.iterate(1, element->element+1)

		.filter(element->element%5==0)

		.limit(5)

		.forEach(System.out::println);

	}

}

Output:

Output

5

10

15

20

25

Java Stream Example: Filtering and Iterating Collection

In this instance, we are utilizing the filter function. It is evident that the code has been streamlined for better efficiency and brevity.

Example

Example

import java.util.*;

class Product{

	int id;

	String name;

	float price;

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

}

public class JavaStreamExample {

	public static void main(String[] args) {

		List<Product> productsList = new ArrayList<Product>();

		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		// This is more compact approach for filtering data

		productsList.stream()

                             .filter(product -> product.price == 30000)

                             .forEach(product -> System.out.println(product.name));	

	}

}

Output:

Output

Dell Laptop

Java Stream Example : reduce Method in Collection

The process involves taking a series of input items and merging them into one concise outcome through iterative actions. For instance, calculating the total of numerical values or gathering elements into a collection.

In this instance, we demonstrate the utilization of the reduce function, employed to calculate the total sum of all product prices.

Example

Example

import java.util.*;

class Product{

	int id;

	String name;

	float price;

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

}

public class JavaStreamExample {

	public static void main(String[] args) {

		List<Product> productsList = new ArrayList<Product>();

		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		// This is more compact approach for filtering data

		Float totalPrice = productsList.stream()

					.map(product->product.price)

					.reduce(0.0f,(sum, price)->sum+price);	// accumulating price

		System.out.println(totalPrice);

		// More precise code 

		float totalPrice2 = productsList.stream()

				.map(product->product.price)

				.reduce(0.0f,Float::sum);	// accumulating price, by referring method of Float class

		System.out.println(totalPrice2);

		

	}

}

Output:

Output

201000.0

201000.0

Java Stream Example: Sum by Using Collectors Methods

Another approach to calculate the total of numerical values is by utilizing collectors. In this instance, we are employing the Collectors class along with its designated techniques to determine the sum of all the prices of products.

Example

Example

import java.util.*;

import java.util.stream.Collectors;

class Product{

	int id;

	String name;

	float price;

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

}

public class JavaStreamExample {

	public static void main(String[] args) {

		List<Product> productsList = new ArrayList<Product>();

		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		// Using Collectors's method to sum the prices.

		double totalPrice3 = productsList.stream()

	                    .collect(Collectors.summingDouble(product->product.price));

		System.out.println(totalPrice3);

		

	}

}

Output:

Output

201000.0

Java Stream Example: Find Max and Min Product Price

The following example demonstrates how to find the minimum and maximum product prices using a stream. This technique offers a more streamlined method for obtaining these values, eliminating the need for an imperative approach.

Example

Example

import java.util.*;  

class Product{  

    int id;  

    String name;  

    float price;  

    public Product(int id, String name, float price) {  

        this.id = id;  

        this.name = name;  

        this.price = price;  

    }  

}  

public class JavaStreamExample {  

    public static void main(String[] args) {  

        List<Product> productsList = new ArrayList<Product>();  

        //Adding Products  

        productsList.add(new Product(1,"HP Laptop",25000f));  

        productsList.add(new Product(2,"Dell Laptop",30000f));  

        productsList.add(new Product(3,"Lenevo Laptop",28000f));  

        productsList.add(new Product(4,"Sony Laptop",28000f));  

        productsList.add(new Product(5,"Apple Laptop",90000f));  

        // max() method to get max Product price   

        Product productA = productsList.stream().max((product1, product2)->product1.price > product2.price ? 1: -1).get();  

        System.out.println(productA.price);  

        // min() method to get min Product price  

        Product productB = productsList.stream().min((product1, product2)->product1.price > product2.price ? 1: -1).get();  

        System.out.println(productB.price);  

          

    }  

}

Output:

Output

90000.0

25000.0

Java Stream Example: count Method in Collection

Example

Example

import java.util.*;

class Product{

	int id;

	String name;

	float price;

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

}

public class JavaStreamExample {

	public static void main(String[] args) {

		List<Product> productsList = new ArrayList<Product>();

		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		// count number of products based on the filter

		long count = productsList.stream()

					.filter(product->product.price<30000)

					.count();

		System.out.println(count);

	}

}

Output:

The Stream API enables us to gather outcomes in a variety of formats. Results can be obtained as sets, lists, or maps, allowing for manipulation of the elements.

Java Stream Example : Convert List into Set

Example

Example

import java.util.*;

import java.util.stream.Collectors;

class Product{

	int id;

	String name;

	float price;

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

}



public class JavaStreamExample {

	public static void main(String[] args) {

		List<Product> productsList = new ArrayList<Product>();



		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		

		// Converting product List into Set

		Set<Float> productPriceList = 

			productsList.stream()

			.filter(product->product.price < 30000)	// filter product on the base of price

			.map(product->product.price)

			.collect(Collectors.toSet());	// collect it as Set(remove duplicate elements)

		System.out.println(productPriceList);

	}

}

Output:

Output

[25000.0, 28000.0]

Java Stream Example: Convert List into Map

Example

Example

import java.util.*;

import java.util.stream.Collectors;

class Product{

	int id;

	String name;

	float price;

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

}



public class JavaStreamExample {

	public static void main(String[] args) {

		List<Product> productsList = new ArrayList<Product>();



		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		

		// Converting Product List into a Map

		Map<Integer,String> productPriceMap = 

			productsList.stream()

						.collect(Collectors.toMap(p->p.id, p->p.name));

			

		System.out.println(productPriceMap);

	}

}

Output:

Output

{1=HP Laptop, 2=Dell Laptop, 3=Lenevo Laptop, 4=Sony Laptop, 5=Apple Laptop}

Method Reference in stream

Example

Example

import java.util.*;

import java.util.stream.Collectors;



class Product{

	int id;

	String name;

	float price;

	

	public Product(int id, String name, float price) {

		this.id = id;

		this.name = name;

		this.price = price;

	}

		

	public int getId() {

		return id;

	}

	public String getName() {

		return name;

	}

	public float getPrice() {

		return price;

	}

}



public class JavaStreamExample {



	public static void main(String[] args) {

		

		List<Product> productsList = new ArrayList<Product>();

		

		//Adding Products

		productsList.add(new Product(1,"HP Laptop",25000f));

		productsList.add(new Product(2,"Dell Laptop",30000f));

		productsList.add(new Product(3,"Lenevo Laptop",28000f));

		productsList.add(new Product(4,"Sony Laptop",28000f));

		productsList.add(new Product(5,"Apple Laptop",90000f));

		

		List<Float> productPriceList = 

				productsList.stream()

					   		.filter(p -> p.price > 30000)	// filtering data

					   		.map(Product::getPrice)			// fetching price by referring getPrice method

					   		.collect(Collectors.toList());	// collecting as list

		System.out.println(productPriceList);

	}

}

Output:

Output

[90000.0]

Java Stream Specializations

Java Streams API provides specific stream variants optimized for processing primitive data types effectively. IntStream is designed for integers, LongStream for long integers, and DoubleStream for doubles. These tailored streams deliver improved efficiency and include specialized operations tailored for numeric calculations, making them ideal for handling primitive numerical data.

  1. Specialized Functions

Streams designed for handling numeric data provide enhanced functionality compared to the general Stream interface. These streams offer specialized methods that simplify mathematical calculations directly on primitive data streams.

  1. Reduction Operations

Reduction operations represent a form of terminal operation that merges all elements within the Stream to produce a singular outcome. They utilize a binary operator to iteratively execute a function, passing on the outcome as the initial argument of the operator for each consecutive application of the function to the subsequent stream element. This approach is particularly effective for condensing or consolidating numerical data.

Java Stream: File Operation

The Java Streams API, which was first introduced in Java 8, offers an effective and clear method for managing streams of data, such as files. Here, "streams" denote a series of elements that enable both sequential and parallel aggregate operations, distinct from InputStream and OutputStream in I/O streams.

Utilizing the Streams API for data manipulation with files includes the tasks of reading data from files, processing it either line by line or in batches, and frequently saving the outcomes to a different file. This functionality is commonly accomplished through the Files class within the java.nio.file package, which harmonizes effectively with the Streams API.

Example

Example

// Import the necessary classes for handling I/O operations and managing lists

import java.io.BufferedReader;

import java.io.FileReader;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

// Define a public class named FileReadExample

public class FileReadExample {

    // Define a private static method that filters strings by length and converts them to uppercase

    private static List<String> filterAndConvertToUpper(List<String> lines, int length) {

        // Create a new ArrayList to store filtered and modified strings

        List<String> filteredStrings = new ArrayList<>();

        // Iterate over each string in the list provided

        for (String line : lines) {

            // Check if the length of the string equals the specified length

            if (line.length() == length) {

                // Convert the string to uppercase and add it to the list of filtered strings

                filteredStrings.add(line.toUpperCase());

            }

        }

        // Return the list of filtered and converted strings

        return filteredStrings;

    }

    // Define the main method, which is the entry point for the program

    public static void main(String[] args) {

        // Specify the path to the file that will be read

        String fileName = "D://hello world//CustomFileReader.txt";

        // Initialize a new ArrayList to store the lines read from the file

        List<String> lines = new ArrayList<>();

        // Use try-with-resources to ensure the BufferedReader is closed properly

        try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {

            String line;

            // Read each line of the file until no more lines are found

            while ((line = br.readLine()) != null) {

                // Add each line to the list of lines

                lines.add(line);

                // Print out each line that is read, for debugging purposes

                System.out.println("Read line: " + line);

            }

            // Call the filterAndConvertToUpper method to process the lines and store the result

            List<String> filteredStrings = filterAndConvertToUpper(lines, 5);

            // Print out the list of filtered and converted strings

            System.out.println("Filtered strings with length 5 (converted to uppercase): " + filteredStrings);

        } catch (IOException e) {

            // Catch and print details of any IOException that occurs during file reading

            e.printStackTrace();

        }

    }

}

Input:

Example

hello

world

Yes

12345

Spaces

Java!

1234

ABCDE

Output:

Output

Read line: hello

Read line: world

Read line: Yes

Read line: 12345

Read line: Spaces

Read line: Java!

Read line: 1234

Read line: ABCDE

Filtered strings with length 5 (converted to uppercase): [HELLO, WORLD, 12345, JAVA!, ABCDE]

Example

Example

import java.io.PrintWriter;

import java.nio.file.Files;

import java.nio.file.Paths;

import java.io.IOException;

import java.util. Stream.Stream;

// Class to demonstrate writing to a file

class FileWriterExample {

    // Main method as the entry point of the application

    public static void main(String[] args) {

        // Array of strings to be written to the file

        String[] phrases = { "Sample", "Text", "For", "File", "Write" };

        // Path to the file where the text will be written

        String filePath = "D://hello world//CustomFileReader.txt";

        // Attempt to open the file and write phrases to it

        try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(Paths.get(filePath)))) {

            // Writing each string from the array to the file using a stream

            Stream.of(phrases).forEach(writer::println);

            // Notify user of successful write operation

            System.out.println("Text has been successfully written to the file.");

        } catch (IOException e) {

            // Handle potential IO exceptions such as file not found or access issues

            e.printStackTrace();

        }

    }

}

Output:

Output

Text has been successfully written to the file.

Input Required

This code uses input(). Please provide values below: