Jdk8-Stream API, detailed description of creation, intermediate operations, and termination operations

Powerful Stream API


1. Stream API description
  • The two most important changes in Java 8 are Lambda expressions and Stream API.

  • Stream API (java.util.stream) introduces the real functional programming style into Java, which is the best supplement to Java class library so far, because Stream API can greatly provide Java programmers with productivity and allow programmers to write Produce more efficient, clean, beautiful, and concise code.

  • Stream is a key concept for processing collections in Java 8. It can specify the operations you want to perform on the collection, and can perform very complex operations such as searching, filtering, and mapping data. Using Stream API to operate on collection data is similar to executing database queries in SQL. You can also use the Stream API to operate in parallel. In short, the Stram API provides an efficient and easy-to-use way of processing data.

  • Persistent databases, such as Mysql, Oracle, etc., are equivalent to data operations at the database level, but with the emergence of NoSQL databases such as MongDB and Radis, data operations need to be performed at the Java level. Use Steam API at this time

  • The difference between Stream and Collection: Collection is a static memory structure. And Stream is about computing. The former is mainly oriented to memory and stored in memory, and the latter is mainly oriented to CPU, and the calculation is realized through CPU.

The collection is data, and Stream is about calculation.
(1) Stream itself does not store elements.
(2) Stream will not change the source object, instead they will return a holding result to the new Stream.
(3) Stream operations are executed delayed, which means that they will wait until the results are needed before execution.

2. Create Stream (Instantiate Stream)

A data source (such as: collection, array), get a stream

  1. Collection Create Stream
@Test
public void test(){
    
    
	//获取一个集合
	List<Employee> list = EmplpyeeData.getEmployees();
	
	//default Stream<E> stream(); 返回一个顺序流
	Stream<Employee> stream = list.stream();
	
	//default Stream<E> parallelStream(); 返回一个并行流
	Stream<Employee> parallelStream = list.parallelStream();
}
  1. Array creation Stream
@Test
public void test(){
    
    
	int[] arr = new int[]{
    
    1,2,3,4,5,6};
	//调用Arrays类的static<T> Stream<T> stream(T[] array);返回一个流
	Instream stream = Arrays.stream(arr);

	Employee e1 = new Employee("1001","Tom");
	Employee e2 = new Employee("1002","Marry");
	Employee[] arr1 = new Employee[]{
    
    e1,e2};
	Stream<Employee> stream1 = Arrays.stream(arr1);
}
  1. Create Stream by Stream of()
@Test
public void test(){
    
    
	Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
}
  1. Create unlimited streams (not commonly used)
  • Help us use when creating data
@Test
public void test(){
    
    

	//迭代
	//public static<T> Stream<T> iterate(final T seed,final UnaryOperator<T> f);
	//遍历前10个偶数(不会停下来)
	Stream.iterate(0,t -> t + 2).forEach(System.out::println);
	//加上限制,只要前十个偶数
	Stream.iterate(0,t -> t + 2)limit(10).forEach(System.out::println);
	
	//生成
	//public static<T> Stream<T> generate(Supplier<T> s);
	Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
3. Intermediate operations (filtering, mapping, sorting)

An intermediate operation chain to process the data of the data source.

  1. Screening and slicing
@Test
public void test(){
    
    
	List<Employee> list = EmployeeData.getEmployees();

	//filter(Predicate p) 接收 Lambda ,从流中排除某些元素
	Stream<Employee> stream = list.stream();
	//查询员工表中薪资>7000的员工信息
	stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);
	//截断流 注意需要冲洗生成流,因为之前已经进行了终止操作
	//是元素不超过给定的数量
	list.stream().limit(3).forEach(System.out::println);
	//skip(n) 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个Null
	list。stream().skip(20).forEach(System.out::println);
	//distinct() 筛选,通过流所生成元素的hashCode()和equals()去除重复元素
	list.stream().distinct().forEach(System.out::println);
}
  1. Mapping
  @Test
    public void test13(){
    
    
		
        List<String> list = Arrays.asList("abc","def","cbd","aaa");
        //map(Function f) 接收一个函数作为参数,该函数提供了某种规则,通过这种规则将原有集合的数据映射到一个新的集合中。
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);

	//练习:获取员工姓名大于三的员工姓名
	List<Emplouyee> list = employeeData.getEmplyees();
	//Stream<String> nameStream = list.stream.map(e -> e.getName());
	Stream<String> nameStream = list.stream.map(Employee :: getName);
	nameStream.filter(name ->name.length()>3).forEach(System.out::println);
    }
	
@Test
public void test(){
    
    
	//flatMap(Function f) 接受一个函数作为参数,将流中的每一个值都换成另一个流,然后把所有流连接成一个流。
	//练习:
	//集合里面套集合的情况时,遍历每一个元素。
	//用map来做
	//注意:StreamAPITest是类名,使用类名::静态方法
	Stream<Stream<Charcator>> streamStream = list.stream().map(StreamAPITest :: fromStringtoStream);
	streamStream.forEach(s ->{
    
    
		s.forEach(System.out::println)
	});	
	//用flatMap来做
	Stream<Charactor> charactorStream = list.stream().flatMap(StreamAPITest1::fromStringToStream);
	charactorStream.forEach(System.out::println);
}
public static Stream<Charcater> fromStringToStream(String str){
    
    
	ArrayList<Character> list = new ArrayList<>();
	for(Charactor c : str.toCharArray()){
    
    
		list.add(c);
	}
	return list.stream();
}

  1. Sort
@Test
public void test(){
    
    

	//sorted() 自然排序
	List<Integer> list = Arrays.asList(1,2412,3423,54,3234,645,1,212,-13,11);
	list.stream().sorted().forEach(System.out::println);

	//对象的排序,sorted(Comparator com) 定制排序
	//需要实现接口
	List<Employee> list = employeeData.getEmployees();
	list.stream().sorted((e1,e2) -> {
    
    
		int ageValue = Integer.compare(e1.getAge(),e2.getAge());
		//按照年龄进行排序,如果年龄相等按照工资进行排序
		if(ageValue != 0){
    
    
			return ageValue;
		}else{
    
    
			return - Double.compare(e1.getSalary(),e2.getSalary());
		}	
	}).forEach(System.out::println);
}
4. Terminate operation (terminal operation)

Once the termination operation is executed, the intermediate operation chain is executed and the result is generated, after which it will not be used again. If you want to reuse it, you need to recreate a Stream

  1. Match and find
List<Employee> list = EmployeeData.getEmployees();
//allMatch(Predicate p) 检查是否匹配所有元素
//练习:是否所有员工的年龄都大于18
boolean allMatch = list.stream().allMatch(e -> e.getAge() > 18);

//anyMatch(Predicate p) 检查是否至少匹配一个元素。
//练习:是否存在员工的工资大于10000
boolean anyMatch = list.stream().anyMatch(e -> e.getSalary() > 10000);

//noneMatch(Predicate p) 检查是否没有匹配的元素,有返回false,没有返回true
//练习:是否存在员工姓”雷“ 
boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startWitch("雷"))//findFirst()返回第一个元素,可以结合排序来写

//findAny() 返回当前流中的任意元素

//count() 返回流中元素的总个数
long count = list.stream().filte(e -> e.getSalary() > 5000).count();

//max(Comparator c) 返回流中最大值
//练习 求员工中最高工资
//使用map先映射到工资...
Stream<Double> salaryStream = employees.stream().map(e - >e.getSalary());
Optional<Double> maxSalary = salarySaream.max(Double :: compare);

//min(Comparator c) 返回流中最小值
//求最低工资的员工信息
Optional<Employee> employee = list.stream().min((e1,e2) -> Double.compare(e1.getSalary(),e2.getSalary()));

//forEach(Cousumer c) 内部迭代
list.stream().forEach(System.out::println);
//注意与集合中的forEach()进行区分
list.forEach(System.out::println);
  • External iteration is similar to the previous Iterator. The pointer points to the collection externally, and the next() method needs to be called to move the pointer down, while the internal iteration is equivalent to being automatically performed inside the collection.
  1. Statute
@Test
public void test14(){
    
    

    //T reduce(T identity, BinaryOperator<T> accumulator); 可以将流中元素反复结合起来,得到一个值,返回一个T
	List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
	Integer reduce = list.stream().reduce(0, Integer::sum);
	System.out.println(reduce);
	
	//Optional<T> reduce(BinaryOperator<T> accumulator); 可以将流中元素反复结合起来得到一个值,返回Optional<T>
	//计算公司中所有员工工资的总和
	List<Employee> list = EmployeeData.getEmployees();
	Stream<Double> salaryStream = list.stream().map(Employee :: getSalary);
	Optional<Employee> countMoney = salaryStream.reduce(Double :: sum);
	
	//或者也可以自己写累加
	Optional<Employee> countMoney = salaryStream.reduce((d1,d2) -> d1 + d2);
}
  1. collect
@Test
public void test(){
    
    
	
	//collect(Collector c) 将流转化为其他形式,接收一个Collector接口的实现,用于
	List<Employee> list = EmployeeData.getEmployees();
	//将工资中大于6000的放到一个list中
	List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
	employeeList.forEach(System.out::println);
	
	//也可以放到一个set集合中,只需要调用Collectors中写好的静态方法就可以了
	List<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
	employeeSet.forEach(System.out::println);
}
  • Collectors internal static method
    Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_43941676/article/details/108547305