Java 8 Stream API Part 2

In previous post, we dealt with the functional interfaces which are used by Stream API. In this tutorial we will learn how to work with Stream API with examples.

A stream represents a sequence of elements and supports different kind of operations to perform computations upon those elements.

Stream are of two types – serial or parallel. There are two methods parallelStream() and stream() to get parallel or serial stream.

Stream Creation

Stream can be obtained by several ways.

  1. Using stream() and parallelStream() methods.
  2. Using Stream.of()
  3. Using Stream.generate()
  4. Using Stream.iterate()
 String[] array = {"a", "b", "c", "d", "e"};
 //Arrays.stream
 Stream<String> stream1 = Arrays.stream(array);
 //Stream.of()
 Stream<String> stream2 = Stream.of("d2", "a2", "b1", "b3", "c");

//generate infinite stream of Hello String
Stream<String> stream3 = Stream.generate(()->"Hello");

ArrayList<String> list = Arrays.asList("A1","A2","A3");
//List.stream() to get serial stream
Stream<String> stream4 = list.stream();

Stream Operations

There are two types of stream operations Intermediate and Terminal.

Intermediate operations are lazy in nature means nothing going to happen until and unless terminal operation invoked . They return a stream object so we can chain multiple intermediate operations. Intermediate operations are of two types Stateful and Stateless. Stateful intermediate operations are those which maintain information from a previous invocation internally to be used again in a future invocation of the method like distinct(),sorted(). Stateless intermediate operations are those which does not care about the previous invocation like filter(),map(),flatMap()

Terminal operation is used to finish the stream and yields  a non-stream result as no-value at all,a collection or a primitive value.

Common Stream Operations

  1. filter()
  2. map()
  3. collect()
  4. flatMap()
  5. limit()
  6. sorted()
  7. collect()
  8. forEach()
  9. distinct()
  10. count()
  11. allMatch()
  12. noneMatch()
  13. anyMatch()

Read More

Lets Play with Stream API

Here we will have examples of Stream Operations.

1)Find out the names starting letter “A”


List<String> listOfNames= Stream.of("Amit","Raj","Ajay","Basant")
.filter(s->s.startsWith("A"))
.collect(Collectors.toList());

2)Find the employee with max  salary without max() method
Here we have called sorted() method to sort the employees and then find the first employee who getting max salary.For this you need to implement Comparable interface and then finally we have called findFirst() method  to get first element.

class Employee implements Comparable<Employee>{
int id;
double salary;

public Employee(int id, double salary) {
super();
this.id = id;
this.salary = salary;
}

@Override
public String toString() {
return "Employee [id=" + id + ", salary=" + salary + "]";
}

@Override
public int compareTo(Employee o) {
return (int) (o.salary-salary);
}

}
Employee e1 = new Employee(1,15000);
Employee e2 = new Employee(1,1000);
Employee e3 = new Employee(1,20000);
List<Employee> listEmp = Arrays.asList(e1,e2,e3);
Optional<Employee> emp = listEmp.stream()
				.sorted()
				.findFirst();

3)Get the list of names start from letter “A” and convert the names in uppercase.

	List<String> listOfNames= Stream.of("Amit","Raj","Ajay","Basant")
				             .filter(s->s.startsWith("A"))
				             .map(s->s.toUpperCase())
				             .collect(Collectors.toList());

4)Print all the employees whose salary less than 10000

                listEmp.stream()
                       .filter(e->e.getSalary()<10000)
                       .forEach(System.out::println);

5)Remove all the duplicates records from the list of employees.

For this you need to override equals() and hashCode() methods in your class(here Employee).

listEmp.stream()
	.distinct()
	.forEach(System.out::println);

6)Sort employees by salary and find first two employees

 
List<Employee> empList = listEmp.stream()
                                       .sorted()
                                       .limit(2)
                                       .collect(Collectors.toList());
 

7)Convert List<Employee> to Map<Integer,Employee>

Collectors has many method to convert to List,Map and Set.

  • toList()
  • toMap()
  • toSet()
Map<Integer,Employee> empList = listEmp.stream()
                                       .sorted()
                                       .collect(Collectors.toMap(e->e.id,e->e));

8)Combines two List using flatMap()
Lets we have a list in which each element itself is List. So here we are consolidating them to form a single list.

Employee e1 = new Employee(1,15000);
Employee e2 = new Employee(2,1000);
Employee e3 = new Employee(3,7000);

List<Employee> listEmp1 = Arrays.asList(e1,e2);
List<Employee> listEmp2 = Arrays.asList(e3);

List<List<Employee>> listEmployees = Arrays.asList(listEmp1,listEmp2);

List<Employee> listEmp3 = listEmployees.stream()
.flatMap(e->e.stream())
.collect(Collectors.toList());

9)Filter List<Employee> and convert List<EmployeeDetail>

class EmployeeDetail{
	private int id;
	private double salary;
	public EmployeeDetail(Employee e) {
		super();
		this.id = e.getId();
		this.salary = e.getSalary();
	}
	@Override
	public String toString() {
		return "EmployeeDetail [id=" + id + ", salary=" + salary + "]";
	}
}
List<EmployeeDetail> listEmp3	= listEmp1.stream()
				          .map(EmployeeDetail::new)
				          .collect(Collectors.toList());

10)Print the employee detail who getting max salary using max() 

The max() method receive Comparator as input here we have provided it through lambda expression.


listEmp.stream()
.max((e1,e2)->(int)(e1.getSalary()-e2.getSalary()))
.ifPresent(System.out::println);

Leave a Reply