Java8之Stream API

Java 8 API添加了一個新的抽象稱爲流Stream,可以讓你以一種聲明的方式處理數據。
Stream API可以極大提高Java程序員的生產力,讓程序員寫出高效率、乾淨、簡潔的代碼。
這種風格將要處理的元素集合看作一種流, 流在管道中傳輸, 並且可以在管道的節點上進行處理, 比如篩選, 排序,聚合等。
元素流在管道中經過中間操作(intermediate operation)的處理,最後由最終操作(terminal operation)得到前面處理的結果。

一、Stream的3個步驟

1)創建Stream
2)中間操作
3)終止操作

二、創建Stream

#########創建Stream ##########
//第一種
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();

//第二種
Employee[] employees = new Employee[10];
Stream<Employee> stream2 = Arrays.stream(employees);

//第三種 通過of接受不定長參數
Stream<String> stream3 = Stream.of("a","b","c");

//第四種1:無限流,迭代
Stream<Integer> iterate = Stream.iterate(0, (x) -> x+2);

//第四種2:無限流,生成
Stream<Double> generate = Stream.generate(() -> Math.random());

三、中間操作-篩選與切片

###################中間操作#####################
在這裏插入圖片描述
----->使用distinct需要重寫實體的hashCode()和equals()方法
在這裏插入圖片描述
在這裏插入圖片描述

四、中間操作-映射

在這裏插入圖片描述
舉例如下圖:
2者區別:

五、中間操作-排序

在這裏插入圖片描述
舉例如下圖:
在這裏插入圖片描述

六、中間操作-查找和匹配

注意:filter時候,字符串比較必須用equals,否則不能過濾。

	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66, Status.BUSY),
			new Employee(101, "張三", 18, 9999.99, Status.FREE),
			new Employee(103, "王五", 28, 3333.33, Status.VOCATION),
			new Employee(104, "趙六", 8, 7777.77, Status.BUSY),
			new Employee(104, "趙六", 8, 7777.77, Status.FREE),
			new Employee(104, "趙六", 8, 7777.77, Status.FREE),
			new Employee(105, "田七", 38, 5555.55, Status.BUSY)
	);
	/*
		allMatch——檢查是否匹配所有元素
		anyMatch——檢查是否至少匹配一個元素
		noneMatch——檢查是否沒有匹配的元素
		findFirst——返回第一個元素
		findAny——返回當前流中的任意元素
		count——返回流中元素的總個數
		max——返回流中最大值
		min——返回流中最小值
	 */
	@Test
	public void test1(){
		boolean bl = emps.stream()
			.allMatch((e) -> e.getStatus().equals(Status.BUSY));
		
		System.out.println(bl);
		
		boolean bl1 = emps.stream()
			.anyMatch((e) -> e.getStatus().equals(Status.BUSY));
		
		System.out.println(bl1);
		
		boolean bl2 = emps.stream()
			.noneMatch((e) -> e.getStatus().equals(Status.BUSY));
		
		System.out.println(bl2);
	}
	
	@Test
	public void test2(){
		Optional<Employee> op = emps.stream()
			.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
			.findFirst();
		
		System.out.println(op.get());
		
		System.out.println("--------------------------------");
		
		Optional<Employee> op2 = emps.parallelStream()
			.filter((e) -> e.getStatus().equals(Status.FREE))
			.findAny();
		
		System.out.println(op2.get());
	}
	
	@Test
	public void test3(){
		long count = emps.stream()
						 .filter((e) -> e.getStatus().equals(Status.FREE))
						 .count();
		
		System.out.println(count);
		
		Optional<Double> op = emps.stream()
			.map(Employee::getSalary)
			.max(Double::compare);
		
		System.out.println(op.get());
		
		Optional<Employee> op2 = emps.stream()
			.min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
		
		System.out.println(op2.get());
	}
	
	//注意:流進行了終止操作後,不能再次使用
	@Test
	public void test4(){
		Stream<Employee> stream = emps.stream()
		 	.filter((e) -> e.getStatus().equals(Status.FREE));
		
		long count = stream.count();
		stream.map(Employee::getSalary)
			.max(Double::compare);
	}

七、終止操作-歸約和蒐集

/*
	歸約
	reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以將流中元素反覆結合起來,得到一個值。
 */
@Test
public void test1(){
   List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
   
   Integer sum = list.stream()
   	.reduce(0, (x, y) -> x + y);
   
   System.out.println(sum);
   
   System.out.println("----------------------------------------");
   
//使用optional可以避免空指針
//map-reduce的配合使用很經典,map提取,reduce歸約
   Optional<Double> op = emps.stream()
   	.map(Employee::getSalary)
   	.reduce(Double::sum);
   
   System.out.println(op.get());
}

//需求:搜索名字中 “六” 出現的次數
@Test
public void test2(){
   Optional<Integer> sum = emps.stream()
   	.map(Employee::getName)
   	.flatMap(TestStreamAPI1::filterCharacter)
   	.map((ch) -> {
   		if(ch.equals('六'))
   			return 1;
   		else 
   			return 0;
   	}).reduce(Integer::sum);
   
   System.out.println(sum.get());
}

//collect——將流轉換爲其他形式。接收一個 Collectors接口的實現,用於給Stream中元素做彙總的方法
@Test
public void test3(){
   List<String> list = emps.stream()
   	.map(Employee::getName)
   	.collect(Collectors.toList());
   
   list.forEach(System.out::println);
   
   System.out.println("----------------------------------");
   
   // 將所有人的姓名取出,並將其放到set集合中
   Set<String> set = emps.stream()
   	.map(Employee::getName)
   	.collect(Collectors.toSet());
   //  集合遍歷
   set.forEach(System.out::println);

   System.out.println("----------------------------------");
   
   HashSet<String> hs = emps.stream()
   	.map(Employee::getName)
   	.collect(Collectors.toCollection(HashSet::new));
   
   hs.forEach(System.out::println);
}

@Test
public void test4(){
   // 獲取最高薪水的值
   Optional<Double> max = emps.stream()
   		.map(Employee::getSalary)
   		.collect(Collectors.maxBy(Double::compare));
   
   System.out.println(max.get());
   
   // 獲取最小薪水的值
   Optional<Employee> op = emps.stream()
   		.collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
   
   System.out.println(op.get());
   
   // 求所有人薪水的和
   Double sum = emps.stream()
   		.collect(Collectors.summingDouble(Employee::getSalary));
   
   System.out.println(sum);
   
   // 求所有人薪水的平均值
   Double avg = emps.stream()
   		.collect(Collectors.averagingDouble(Employee::getSalary));
   
   System.out.println(avg);
   
   // 求個數
   Long count = emps.stream()
   		.collect(Collectors.counting());
   
   System.out.println(count);
   
   System.out.println("--------------------------------------------");
   
   DoubleSummaryStatistics dss = emps.stream()
   		.collect(Collectors.summarizingDouble(Employee::getSalary));
   
   System.out.println(dss.getMax());
}

//分組
@Test
public void test5(){
   Map<Status, List<Employee>> map = emps.stream()
   	.collect(Collectors.groupingBy(Employee::getStatus));
   
   System.out.println(map);
}

//多級分組
@Test
public void test6(){

   // 按照不同年齡區間和狀態分組
   Map<Status, Map<String, List<Employee>>> map = emps.stream()
   	.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
   		if(e.getAge() >= 60)
   			return "老年";
   		else if(e.getAge() >= 35)
   			return "中年";
   		else
   			return "成年";
   	})));
   
   System.out.println(map);
}

//分區
@Test
public void test7(){
    // 以5000爲基準分組,大於5000的一組,小於的一組
   Map<Boolean, List<Employee>> map = emps.stream()
   		.collect(Collectors.partitioningBy((e) -> e.getSalary() >= 5000));
   
   System.out.println(map);
}

//
@Test
public void test8(){
   // 將所有人的姓名name用逗號分隔,轉化成字符串
   String str = emps.stream()
   		.map(Employee::getName)
   		.collect(Collectors.joining("," , "----", "----"));
   
   System.out.println(str);
}

@Test
public void test9(){
   // 求所有人薪水的和
   Optional<Double> sum = emps.stream()
   		.map(Employee::getSalary)
   		.collect(Collectors.reducing(Double::sum));
   System.out.println(sum.get());
}

ok,常用的stream操作基本就是這些了。其他的可以點擊源碼進行查看研究。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章