JAVA basics - Stream flow (java advanced notes)


You can read all the java advanced notes from this buddy

1. Getting to know Stream for the first time

insert image description here
Through the following code, we clearly see that it is more convenient to use Stream, but it is a bit complicated to use ordinary collection traversal.

public class Test01 {
    
    
	public static void main(String[] args) {
    
    
		ArrayList<String> list1 = new ArrayList<>();
		list1.add("张无忌");
		list1.add("周正若");
		list1.add("赵斌");
		list1.add("张强");
		list1.add("张三丰");
 
		// Stream流
		list1.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3)
				.forEach(name -> System.out.println(name));
		// 张无忌
		// 张三丰
 
		// 1.把所有“张”姓开头元素存储到新集合
		ArrayList<String> list2 = new ArrayList<>();
		for (String name : list1) {
    
    
			if (name.startsWith("张")) {
    
    
				list2.add(name);
			}
		}
		System.out.println(list2); // [张无忌, 张强, 张三丰]
 
		// 2.把所有“张”姓开头且长度为3的元素存储到新集合
		ArrayList<String> list3 = new ArrayList<>();
		for (String name : list2) {
    
    
			if (name.length() == 3) {
    
    
				list3.add(name);
			}
		}
		System.out.println(list3); // [张无忌, 张三丰]
	}
}

2. Stream overview

For example, in the small example above, the idea of ​​Stream flow is as follows:
insert image description here
The function of Stream flow is:

3. Steps to use Stream

Combining Lambda expressions to simplify operations on collections and numbers.

  1. First get a Stream (pipeline) and put the data on it.
  2. Use intermediate methods to operate on data on the pipeline.
  3. Use finalizer methods to operate on data on the pipeline.
filter, convert intermediate method After the method is called, you can call other methods
statistics, printing Termination method In the last step, after the call is completed, other methods cannot be called

1. Get Stream

method of obtaining method name illustrate
single-column collection default Stream stream() Default methods in Collection
two-column set none The stream cannot be used directly, it needs to be converted into a single-column collection through keySet() or entrySet()
array public static Stream stream(T[ ] array) Static method in Arrays tool class
a bunch of scattered data public static Stream of(T… values) Static method in stream interface

1.1 Single column set

public class StreamTest {
    
    
	public static void main(String[] args) {
    
    
		//单列集合获取Stream流
		ArrayList<String> list = new ArrayList<>();
		Collections.addAll(list, "a","b","c","d","e");
		//获取到一个流水线,并把集合中的数据方法流水线上
		//Stream<String> stream1 = list.stream();
		//使用终结方法打印流水线上数据
		//stream1.forEach( s ->System.out.println(s) );
		
		list.stream().forEach(s -> System.out.println(s));
	}
}

1.2 Two-column collection

public class StreamTest {
    
    
	public static void main(String[] args) {
    
    
		
		//双列集合获取Stream流 
		//1. 创建双列集合
		HashMap<String, Integer> hm = new HashMap<>();
		//2. 添加数据
		hm.put("aaa", 111);
		hm.put("bbb", 222);
		hm.put("ccc", 333);
		//3.1 获取Stream流方法一: keySet()
		//键
		 hm.keySet().stream().forEach(s -> System.out.println(s));
		//3.2 获取Stream流方法二:entrySet()
		 //键值对
		hm.entrySet().stream().forEach(s -> System.out.println(s));	 
	}
}

1.3 Arrays

Details of the static method of in the Stream interface:

  • The formal parameter of the method is a variable parameter, which can pass a bunch of scattered data or an array.
  • But the array must be a reference data type.
  • If the basic data type is passed, the entire array will be equivalent to an element and put into a stream.
public class StreamTest {
    
    
	public static void main(String[] args) {
    
    
		
		//数组获取Stream流 
		//1.创建基本数据类型数组
		int[] arr1 = {
    
    1,2,3,4,5,6,7,8,9,10};
		//获取stream
		Arrays.stream(arr1).forEach(s -> System.out.println(s));
		
		//2.创建引用数据类型数组
		String[] arr2 = {
    
    "a","b","c"};
		//获取stream
		Arrays.stream(arr2).forEach(s -> System.out.println(s));
		
		//方式是错误的!!!
		//Stream接口中静态方法of的细节
		//方法的形参是一个可变参数,可以传递一堆零散数据,也可以传递数组
		//但是数组必须是引用数据类型
		//如果传递的是基本数据类型,是会把整个数组相当做一个元素,放到一个stream流当中
		Stream.of(arr2).forEach(s -> System.out.println(s));
		Stream.of(arr1).forEach(s -> System.out.println(s)); //[I@1b28cdfa
	}
}

1.4 Scattered data

Details: A bunch of scattered data needs to be of the same data type.

public class StreamTest {
    
    
	public static void main(String[] args) {
    
    
		//零散数据获取Stream流 
		
		//基本数据类型
		Stream.of(1,2,3,4,5).forEach(s -> System.out.println(s));
		
		//引用数据类型
		Stream.of("a","b","c","d","e").forEach(s -> System.out.println(s));
	}
}

2. Intermediate method of Stream

method name illustrate
Stream filter ( Predicate<? super T> predicate ) filter
Stream filter ( Predicate<? super T> predicate ) Get the first few elements
Stream skip ( long n ) skip the first few elements
Stream distinct ( ) Element deduplication, dependency (hashCode and equals methods)
static Stream concat ( Stream a , Stream b ) Merge two streams a and b into one stream
Stream map ( Function<T ,R> mapper ) Converting Data Types in a Stream

Note 1: The intermediate method returns a new Stream. The original Stream can only be used once. It is recommended to use chain programming.
Note 2: Modifying the data in the Stream stream will not affect the data in the original collection or array.

public class StreamTest01 {
    
    
	public static void main(String[] args) {
    
    
		//1.过滤:把开头的留下,其余数据过滤不要
		ArrayList<String> list = new ArrayList<>();
		Collections.addAll(list, "张三","李四","王五","赵六","张七");
		
		ArrayList<String> list2 = new ArrayList<>();
		Collections.addAll(list2, "张三","李四","王五","赵六","张三");
		
		ArrayList<String> list3 = new ArrayList<>();
		Collections.addAll(list3, "孙七","钱八");
		
		ArrayList<String> list4 = new ArrayList<>();
		Collections.addAll(list2, "张三-23","李四-24","王五-25");
		
		list.stream().filter(new Predicate<String>() {
    
    
			//匿名内部类太麻烦 需要缩写
			@Override
			public boolean test(String s) {
    
    
				//如果返回值为true,表示当前数据留下
				//如果返回值为false,表示当前数据舍弃
				return s.startsWith("张");
				
			}
		}).forEach(s -> System.out.println(s)); //张三 张七
		
		list.stream()
		    .filter(s -> s.startsWith("张"))
		    .forEach(s -> System.out.println(s));
		
		//2. 获取前几个元素  
		list.stream()
		    .limit(3)
		    .forEach(s -> System.out.println(s));  //张三 李四 王五
		//3. 跳过
		list.stream()
		    .skip(4)
		    .forEach(s -> System.out.println(s));  //张七
		
		//4.去重
		list2.stream()
		     .distinct()
		     .forEach(s -> System.out.println(s)); //张三 李四 王五 赵六
		
		//5. 合并
		Stream.concat(list2.stream(), list3.stream())
		      .forEach(s -> System.out.println(s));
		
		//6.转换数据类型
		//只能获取集合里面的年龄并打印
		//第一个类型:流中原本的数据类型
		//第二个类型:将要转变成为的数据类型
		list4.stream().map(new Function<String,Integer>() {
    
    
			@Override
			//apply: 依次表示流中的每一盒数据
			//返回值:表示转化之前的数据
			public Integer apply(String s) {
    
    
				String[] arr = s.split("-");
				String ageString = arr[1];
				int age = Integer.parseInt(ageString);
				return age;
			}
		}).forEach(s -> System.out.println(s));
		
		list.stream()
		    .map(s ->Integer.parseInt(s.split("-")[1]))
		    .forEach(s -> System.out.println(s));
	}
}

3. The termination method of the Stream stream

method name illustrate
void forEach ( Consumer action ) traverse
long count ( ) statistics
toArray ( ) Collect the data in the stream and put it into an array
collect ( Collector collector ) Collect the data in the stream and put it in the collection
public class StreamTest02 {
    
    
	public static void main(String[] args) {
    
    
		ArrayList<String> list = new ArrayList<>();
		Collections.addAll(list, "张三", "李四", "王五", "赵六");
 
		// 遍历
 
		// Consumer的泛型:表示流中的数据类型
		// accept方法的形参s:依次表示流中的每一个数据
		//
		list.stream().forEach(new Consumer<String>() {
    
    
			@Override
			public void accept(String s) {
    
    
				System.out.println(s);
			}
		});
 
		list.stream().forEach(s -> System.out.println(s)); // 张三 李四 王五 赵六
 
		// 统计
		long count = list.stream().count();
		System.out.println(count); // 4
 
		// 收集数据放进数组
		Object[] arr1 = list.stream().toArray();
		System.out.println(Arrays.toString(arr1)); // [张三, 李四, 王五, 赵六]
 
		// 指定数据类型
		// Infunction的泛型:具体类型的数组
		// apply中形参:流中数据的个数,要跟数组长度一致
		// apply的返回值:具体类型的数组
		String[] arr2 = list.stream().toArray(new IntFunction<String[]>() {
    
    
			@Override
			public String[] apply(int value) {
    
    
				return new String[value];
			}
		});
		// toArray方法中的参数:只是创建一个指定类型的数组
		// toArray底层: 会此意得到流中的每一个数据,并把数据放到数组中
		// toArray的返回值:是一个装着流里面所有数据的数组
		System.out.println(Arrays.toString(arr2));
 
		// lambda表达式
		String[] arr3 = list.stream().toArray(value -> new String[value]);
		System.out.println(Arrays.toString(arr3));
	}
}

collect method:

public class StreamTest {
    
    
	public static void main(String[] args) {
    
    
		ArrayList<String> list = new ArrayList<>();
		Collections.addAll(list, "张三-男-23", "李四-男-24", 
                        "王五-男-25", "赵六-女-27", "孙八-女-28");
 
		//收集到List集合当中
		//需求:
		//将所有的男性收集起来
		List<String> newList = list.stream()
				.filter(s-> "男".equals(s.split("-")[1]))
				.collect(Collectors.toList());
		System.out.println(newList);  //[张三-男-23, 李四-男-24, 王五-男-25]
		
		//收集到Set集合当中
		Set<String> newSet = list.stream()
				.filter(s-> "男".equals(s.split("-")[1]))
				.collect(Collectors.toSet());
		System.out.println(newSet);
		
		//收集到Map集合当中
		//键: 姓名  值: 年龄
		
		//toMap:
		//参数一表示键的生成规则  参数二表示值得生成规则
		//参数一:  
		//Function泛型一:表示流中每一个数据的类型 ;
		//        泛型二:表示Map集合中键的数据类型
		//方法apply 形参:一次表示流里面的每一个数据
		//        方法体:生成键的代码 
		//        返回值:已生成的键
		//参数二:
		//Function泛型一:表示流中每一个数据的类型 ;
		//        泛型二:表示Map集合中值的数据类型
		//方法apply 形参:一次表示流里面的每一个数据
		//        方法体:生成值的代码 
		//        返回值:已生成的值
		Map<String, Integer> newMap = list.stream()
		.filter(s-> "男".equals(s.split("-")[1]))
		.collect(Collectors.toMap(new Function<String, String>() {
    
    
			@Override
			public String apply(String s) {
    
    
				return s.split("-")[0];
			}
		}, new Function<String, Integer >() {
    
    
			@Override
			public Integer apply(String s) {
    
    
				return Integer.parseInt(s.split("-")[2]);
			}
		}));
		System.out.println(newMap);  //{李四=24, 张三=23, 王五=25}
		
		//lambda表达式
		Map<String, Integer> newMap1 = list.stream()
				.filter(s-> "男".equals(s.split("-")[1]))
				.collect(Collectors.toMap( 
						s-> s.split("-")[0], 
						s-> Integer.parseInt(s.split("-")[2])));
		System.out.println(newMap1);
	}
}

4. Practice

1. Data filtering

Requirements:
Define a set and add some integers 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
to filter odd numbers and leave only even numbers.
and save the result

public class StreamDemo {
    
    
	public static void main(String[] args) {
    
    
		// 1.定义一个集合
		ArrayList<Integer> list = new ArrayList<>();
		// 2.添加数据
		Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
 
		// 3.过滤奇数,只留偶数
		// 进行判断,如果是偶数,返回true
		List<Integer> list2 = list.stream()
				.filter(n -> n % 2 == 0)
				.collect(Collectors.toList());
		System.out.println(list2); //[2, 4, 6, 8, 10]
	}
}

2. Data manipulation - filter by age

Requirement:
Create an ArrayList collection, and add the following string, the string is preceded by the name, followed by the age
"zhangsan, 23",
"lisi, 24"
"wangwu, 25"
to keep people whose age is greater than or equal to 24 years old, and the result Collected into the Map collection, the name is the key, and the age is the value

public class StreamDemo {
    
    
	public static void main(String[] args) {
    
    
		// 1.定义一个集合
		ArrayList<String> list = new ArrayList<>();
		//2.集合添加字符串
		list.add( "zhangsan,23");
		list.add("lisi,24");
		list.add("wangwu,25");
		//3.保留年龄大于24岁的人
		Map<String, Integer> map = list.stream()
		.filter(s -> Integer.parseInt(s.split(",")[1]) >= 24)
		.collect(Collectors.toMap(
				s -> s.split(",")[0], 
				s -> Integer.parseInt(s.split(",")[1])));
		System.out.println(map);  //{lisi=24, wangwu=25}
	}
}

3. Data manipulation - performer information request screening

Now there are two ArrayList collections,
the first collection: store the names and ages of 6 actors. In the second collection: store the names and ages of 6 actresses. Separate name and age with a comma. For example: Zhang San, 23
requires the completion of the following operations:
Actors only need the first two characters whose names are 3 characters,
and actresses only need the surname Yang, and the first one is not required.
Merge the filtered actor names and actress names together
Encapsulate the actor information in the previous step into an Actor object.
Save all actor objects to the List collection.
Remarks: actor class Actor, the attributes are: name, age

public class StreamDemo {
    
    
	public static void main(String[] args) {
    
    
		// 1.定义两个集合
		ArrayList<String> manList = new ArrayList<>();
		ArrayList<String> womenList = new ArrayList<>();
 
		// 2.添加数据
		Collections.addAll(manList, "蔡坤坤,24", "叶购成,23", "刘不甜,22", "吴签,24", "谷嘉,30", "肖梁梁,27");
		Collections.addAll(womenList, "赵小颖,35", "杨颖,36", "高元元,43", "张天天,31", "刘诗,35", "杨小幂,33");
 
		// 3. 男演员只要名字为3个字的前两个人
		Stream<String> stream1 = manList.stream()
		.filter(s -> s.split(",")[0].length() == 3)
		.limit(2);
//		.forEach(s -> System.out.println(s)); // 蔡坤坤,24  叶购成,23
																													// 叶购成,23
		//4.女演员只要姓杨的 并且不要第一个
		Stream<String> stream2 = womenList.stream()
		.filter(s -> s.split(",")[0].startsWith("杨"))
		.skip(1);
//		.forEach(s -> System.out.println(s));  //杨小幂,33
		
		//5.把过滤的男演员和女演员信息合并在一起
		//演员信息封装进Actor对象
		
		//String -> Actor对象(类型转换)
		List<Actor> list = Stream.concat(stream1, stream2)
		.map(s -> new Actor(s.split(",")[0],Integer.parseInt(s.split(",")[1])))
		.collect(Collectors.toList());
		System.out.println(list);
	}
}

Guess you like

Origin blog.csdn.net/weixin_68658847/article/details/130534700