【Java】Stream流式编程实战

JDK8引入Stream编程
函数式接口: 函数描述符

* Runnable    ()-> Void
* Callable    ()-> T

     接口名                方法名     	  函数描述符  	  含义          
| Predicate<T>    	| test()     	| T->boolean  	| 判断         |
| Consumer<T>      	| accept()   	| T->void     	| 消费         |
| Function<T,R>    	| apply()    	| T->R        	| 转换         |
| Supplier<T>      	| get()      	| ()->T        	| 供应商       |
| BiConsumer<T,U>   	| accept()   	| (T,U)->void 	| 复杂特化     |
| BiFunction<T,U,R> 	| apply()    	| (T,U)->R    	|              |
| UnaryOperator<T>  	| apply()    	| T->T        	|              |
| IntFunction<R>    	| apply()    	| int->R      	| 基本类型特化 |
| ToIntFunction<T>  | applyAsInt 	| T->int      	|              |

Stream 函数式数据处理

Stream: 处理集合中数据的运算
集合: 负责数据的存储

(1)获得Stream

  1. Collection stream(): 获得单线程的Stream
  2. Collection parallelStream():获得并发的Stream
  3. Arrays.stream(T[]) Stream
  4. Files.lines(Path) Stream 读取文本文件,并把每行文本放入Stream

例:
Stream s = Files.lines(Paths.get("a.txt")); 、、处理英文
Stream s = Files.lines(Paths.get("a.txt") , Charset.forName("GBK")); 处理中文

(2)中间操作

          方法名                               操作描述                               
|     filter(Predicate)     	|       	      对流中的数据做过滤              	|
|        distinct()          	|            去掉流中的重复元素           		|
|       limit(int n)        	|             取流中的前n个元素              	|
|        skip(int n)        	|            跳过流中的前n个元素             	|
|    sorted(Comparator)     	|                  排序                			|
| map(Function<T,R>)  T->R 	|  Stream<R> 对每个元素应用函数,将T对象转换为R对象存入Stream	|
 
例子:
	List<Employee> list = new ArrayList<Employee>();
	//打印所有雇员中年龄有小到大排序后的地第三到第六位的名字:
	list.stream().sorted(Comparator.comparingInt(Employee::getAge)).skip(2).limit(4).map(Employee::getName).forEach(System.out::println); 

(3)收集操作

             方法名                               返回值                 操作描述             
|   allMatch/anyMatch/noneMatch (Predicate<T>)	|   boolean  	| 判断流中的元素是否能够匹配条件  |
|                  count()               	|    long      	|       返回流中的元素数量        |
|       forEach(Consumer<T>)   T->void    	|    void      	|     对流中的所有元素做遍历      |
|           max/min (Comparator<T>)        	| Optional<T> 	|   找出最大的元素/最小的元素     |
|            findAny()/findFirst()         	| Optional<T> 	|  从流中找出任一个/第一个元素    |
|                 collect()                	|              	|            收集元素             |

收集操作collect() ----> 收集器 Collector<T,A,R> Collectors 直接获得Collector

T:流中的元素类型、 A:中间类型、 R:收集之后的结果类型

方法         	         参数            	第三泛型(R)                      方法描述            
|     counting()     	|             无             	|         Long        	|          			 统计个数      				|
|    summingInt()     	|           T->int           	|       Integer      	|            		对整数求和       			 	|
|    averagingInt()    	|           T->int           	|        Double      	|          	         对整数求平均数      				|
|    minBy()/maxBy()   	|         (T,T)->int         	|     Optional<T>    	|      		求最小/最大值                  			|
|  summarizingInt()   	|           T->int           	| IntSummaryStatistics 	|   		统计个数,总和,平均数,最大值,最小值    			|
|  toList()/toSet()   	|             无             	|    List<T>/Set<T>  	|   		将Stream中的元素放入List/Set             		|
|  	toMap()       	|         T->K,T->U          	|       Map<K,U>     	|    		 将Stream中的元素放入Map            			|
|  toConcurrentMap()  	|         T->K,T->U          	| ConcurrentMap<K,U>	|   		 将Stream中的元素放入ConcurrentMap       		|
|    joining()      	|             无             	|        String      	|   		 将Stream中的字符串拼接成String         		|
| collectingAndThen() 	| Collector<T,?,R>, R->RR 	|          RR        	|  		 先收集数据,然后对数据做转换         			|
|      mapping()      	|   T->U,Collector<U,?,R>  	|          R         	|  		   先对元素做转换,再收集数据          			|
|    groupingBy()     	|            T->K            	|    Map<K,List<T>> 	| 将每个元素转换为K对象,并以K对象作为分组依据,将所有元素分组,形成Map 	|
	|    groupingBy()     	|   T->K,Collector<T,?,D>  	|       Map<K,D>     	|  		 分组后,再对分组结果做收集            			|
|   partitioningBy()   	|         T->boolean          	| Map<Boolean,List<T>> 	|    		   根据谓词条件,分成2组                     		|
|   partitioningBy()  	| T->boolean,Collector<T,?,D>	|    Map<Boolean,D>    	|     		 分区后,在对分区结果做收集           			|
	

原始流特化

IntStream LongStream DoubleStream
获得原始特化流的方法:

  1. Stream 调用 mapToInt(T->int)
  2. IntStream.range(a,b) a ---> b-1
    IntStream.rangeClosed(a,b) a ---> b
  3. IntStream.generate(()->int ) 由函数生成每个元素
  4. IntStream.iterate(a,int->int) 第一个元素是a,利用函数,通过前一个元迭代计算后一个元素

方法:

  • average() OptionalDouble 求平均数
  • sum() int 求和
  • boxed() Stream

案例:

public class Stream_Student {
	public static void main(String[] args) throws IOException {
//	1.读取Student.txt 将Student对象放入List中 
	//文件中不能有空行
	List<Student> list = Files.lines(Paths.get("D:\Student.txt"), Charset.forName("GBK")).map(Student::new).collect(Collectors.toList());
//	2.统计所有学生中大于18岁的学生人数
	System.out.println("-------2.统计所有学生中大于18岁的学生人数--------");
	long countOfAgeUp18 = list.stream().filter((s) -> s.getAge() >= 18).count();
	System.out.println(countOfAgeUp18);
//	3.打印所有学生中成绩最高的三个学生的名字 
	System.out.println("-------3.打印所有学生中成绩最高的三个学生的名字--------");
list.stream().sorted(Comparator.comparingDouble(Student::getScore).reversed()).limit(3).forEach((s) -> System.out.println(s.getName()));
//	4.把所有学生的名字拼成字符串,用逗号隔开 打印出来
	System.out.println("-------4.把所有学生的名字拼成字符串,用逗号隔开 打印出来--------");
	String nameString = list.stream().map(Student::getName).collect(Collectors.joining(","));
	System.out.println(nameString);
//	5.打印所有的院系名称,要求无重复
	System.out.println("-------5.打印所有的院系名称,要求无重复--------");
	//list.stream().collect(Collectors.groupingBy(Student::getDept)).forEach((k, v) -> System.out.println(k));
	list.stream().map(Student::getDept).distinct().forEach(System.out::println);
//	6.把每个院系的学生名字,拼成字符串,用逗号隔开, 打印出来
	System.out.println("-------6.把每个院系的学生名字,拼成字符串,用逗号隔开, 打印出来--------");
	list.stream().collect(Collectors.groupingBy(Student::getDept)).forEach((k, v) ->
	System.out.println(v.stream().map(Student::getName).collect(Collectors.joining(","))));
//	7.打印每个院系年龄最小的学生的名字
	System.out.println("-------7.打印每个院系年龄最小的学生的名字--------");
	list.stream().collect(Collectors.groupingBy(Student::getDept)).forEach((k, v) -> 
	System.out.println(k + ":" + v.stream().sorted(Comparator.comparingInt(Student::getAge)).limit(1).
			collect(Collectors.toList()).get(0).getName()) );
//	8.打印每个院系的平均成绩
	System.out.println("-------8.打印每个院系的平均成绩--------");
	list.stream().collect(Collectors.groupingBy(Student::getDept)).forEach((k, v) -> 
			System.out.println(k + ":" + v.stream().collect(Collectors.averagingDouble(Student::getScore)).doubleValue()));
//	9.打印平均成绩最高的院系的名称
	System.out.println("-------9.打印平均成绩最高的院系的名称--------");
	Collection<List<Student>>collection = list.stream().collect(Collectors.groupingBy(Student::getDept)).values();
	Optional<Dept> optional = collection.stream().map(Dept::new).max(Comparator.comparingDouble(Dept::getAvgScore));
	System.out.println(optional.get().getName() + " " + optional.get().getAvgScore());
//	10.统计每个院系考试及格和考试不及格的学生人数
	System.out.println("-------10.统计每个院系考试及格和考试不及格的学生人数--------");
		list.stream().collect(Collectors.groupingBy(Student::getDept)).forEach((k, v) -> {
			System.out.print(k + ": ");
			Map<Boolean, Long> collect = v.stream().collect(Collectors.partitioningBy((s) -> 
s.getScore() >= 60,Collectors.counting()));
			System.out.print("及格:" + collect.get(true) + "   ");
			System.out.print("不及格:" + collect.get(false));
			System.out.println();
		});
	}
}

---------------------------------------------------------

class Dept {
	private String name;
	private double avgScore;
	public String getName() {return name;}
	public void setName(String name) {	this.name = name;}
	public double getAvgScore() {	return avgScore;}
	public void setAvgScore(double avgScore) {this.avgScore = avgScore;}
	public Dept(List<Student> list) {
		this.name = list.get(0).getDept();
		this.avgScore = list.stream().collect(Collectors.averagingDouble(Student::getScore));
	}
}

-----------------------------------------------------

class Student {
	private String name;
	private int age;
	private double score;
	private String dept;  //院系
	public String getName() {return name;}
	public void setName(String name) {	this.name = name;}
	public int getAge() {return age;}
	public void setAge(int age) {	this.age = age;}
	public double getScore() {return score;	}
	public void setScore(double score) {this.score = score;	}
	public String getDept() {return dept;}
	public void setDept(String dept) {	this.dept = dept;}
	public Student(String s) {  //构造方法,参数为读取的文本中的一行,不能有空行,不然会有空指针异常
		String[] tmp = s.split("/");
		this.name = tmp[0];
		this.age = Integer.parseInt(tmp[1]);
		this.score = Double.parseDouble(tmp[2]);
		this.dept = tmp[3];
	}
	public String toString() {return "Student [name=" + name + ", age=" + age + ", score=" + score + ", dept=" + dept + "]";}
}
原文地址:https://www.cnblogs.com/jwnming/p/13093826.html