六、JDK1.8—Stream API

Stream

Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

注意:
      ①Stream 自己不会存储元素。
      ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
      ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行

 Stream 的操作三个步

创建 Stream
     一个数据源(如:集合、数组),获取一个流 

中间操作
     一个中间操作链,对数据源的数据进行处理 

终止操作(终端操作)
      一个终止操作,执行中间操作链,并产生结

 

创建 Stream

@Test//创建Stream
public void test() {
	//1. Collection 提供了两个方法  stream() 与 parallelStream()
	List<String> list = new ArrayList<>();
	Stream<String> stream = list.stream(); //获取一个顺序流
	Stream<String> parallelStream = list.parallelStream(); //获取一个并行流

	//2. 通过 Arrays 中的 stream() 获取一个数组流
	Integer[] numArr = new Integer[10];
	Stream<Integer> stream1 = Arrays.stream(numArr);

	//3. 通过 Stream 类中静态方法 of()
	Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5, 6);
	Stream<Integer> stream25 = Stream.of(numArr);//数组

	//4. 创建无限流
	//4.1迭代
	Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2);//创建 Stream
	stream3.limit(10) //中间操作
			.forEach(System.out::println);//终止操作(终端操作)

	//4.2生成
	Stream<Double> stream4 = Stream.generate(Math::random);//创建 Stream
	stream4.limit(2)//中间操作
			.forEach(System.out::println);//终止操作(终端操作)
}

中间操作 

public class TestLDemo {

	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66),
			new Employee(101, "张三", 18, 9999.99),
			new Employee(103, "王五", 28, 3333.33),
			new Employee(104, "赵六", 8, 7777.77),
			new Employee(104, "赵六", 8, 7777.77),
			new Employee(104, "赵六", 8, 7777.77),
			new Employee(105, "田七", 38, 5555.55)
	);

	/*
	Stream 的中间操作
	筛选与切片
		filter--接收 Lambda , 从流中排除某些元素。
		limit--截断流,使其元素不超过给定数量。
		skip(n) -- 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
		distinct--筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
	 */
	@Test
	public void test1() {

		//所有的中间操作不会做任何的处理 正中间操作后产生一个新的Stream
		Stream<Employee> stream = emps.stream()
									   .distinct()
				                       .filter((employee) -> {
											System.out.println("测试中间操作");
										    return employee.getAge() <= 35;
										})
										.limit(3)
										.skip(2);


		//只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”
		stream.forEach(System.out::println);

	}

	/*
	Stream 的中间操作
	映射
		map(Function f)--接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。
	        flatMap(Function f)--接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流
                mapToDouble(ToDoubleFunction f)--接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream。 
	        mapToInt(ToIntFunction f)--接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 IntStream。 
	        mapToLong(ToLongFunction f)--接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 LongStream。
	 */
	@Test
	public void test2() {
		List<String> list = Arrays.asList("aaa","bbb","ccc");
		list.stream()
				.map((str)-> str.toUpperCase())
				.forEach(System.out::println);
		//AAA BBB CCC

		emps.stream().map(Employee::getName)
				.forEach(System.out::println);
		//提取所有员工的名字
	}

	/*
	Stream 的中间操作
	排序
		sorted()--产生一个新流,其中按自然顺序排序(按照对象的Comparable)
                sorted(Comparator comp)--产生一个新流,其中按比较器顺序排序
	 */
	@Test
	public void test3() {
		emps.stream()
				.sorted((emp1,emp2)->{
					if(emp1.getAge()== emp2.getAge()){
						return emp1.getName().compareTo(emp2.getName());
					}else{
						return Integer.valueOf(emp1.getAge()).compareTo(emp2.getAge());
					}
				})
		.forEach(System.out::println);
	}

}

终止操作(终端操作)

public class TestLDemo {

	List<Employee> emps = Arrays.asList(
			new Employee(102, "李四", 59, 6666.66),
			new Employee(101, "张三", 18, 9999.99),
			new Employee(103, "王五", 28, 3333.33),
			new Employee(104, "赵六", 8, 7777.77),
			new Employee(104, "赵六", 3, 7777.77),
			new Employee(104, "赵六", 8, 7777.77),
			new Employee(105, "田七", 38, 5555.55)
	);

	/*
	Stream 终止操作
	查找与匹配
		allMatch(Predicate p)--检查是否匹配所有元素
		anyMatch(Predicate p)--检查是否至少匹配一个元素
		noneMatch(Predicate p)--检查是否没有匹配所有元素
		findFirst()--返回第一个元素
		findAny()--返回当前流中的任意元素
		count()--返回流中元素总数
		max(Comparator c)--返回流中最大值
		min(Comparator c)--返回流中最小值
		reduce(T iden, BinaryOperator b)--可以将流中元素反复结合起来,得到一个值。 返回 T 归约 reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。 返回 Optional<T> 备注:map 和 reduce 的连接通常称为 map-reduce 模式,因 Google 用它 来进行网络搜索而出名。
		forEach(Consumer c)--内部迭代(使用 Collection 接口需要用户去做迭 代,称为外部迭代。相反,Stream API 使用内部 迭代——它帮你把迭代做了)
	 */
	@Test
	public void test1() {

		//所有的员工是否都叫张三
		boolean b1 = emps.stream()
				.allMatch((emp)-> "张三".equals(emp.getName()));
		System.out.println(b1);//false

		//是否有员工叫张三
		boolean b2 = emps.stream()
				.anyMatch((emp) -> "张三".equals(emp.getName()));
		System.out.println(b2);//true

		//所有的员工是否都不叫张三
		boolean b3 = emps.stream()
				.noneMatch((emp) -> "张三".equals(emp.getName()));
		System.out.println(b3);//false

		//获取到员工工资最低的员工信息
		Optional<Employee> optional = emps.stream()
				.sorted((emp1,emp2)->Double.compare(emp1.getSalary(),emp2.getSalary()))
				.findFirst();//Optional  防止空指针异常   将对象封装在Optional 中
		System.out.println(optional.get());

		//员工中工资最高(最低)的是多少
		Optional<Double> max = emps.stream()
				.map(Employee::getSalary)//先获取所有的工资数
				.max(Double::compareTo);
		System.out.println(max.get());

	}

	/*
	Stream 终止操作
	归约
		reduce(T iden, BinaryOperator b)--可以将流中元素反复结合起来,得到一个值。 返回 T 归约
		reduce(BinaryOperator b)--可以将流中元素反复结合起来,得到一个值。 返回 Optional<T>
	收集
		collect(Collector c)--将流转换为其他形式。接收一个 Collector接口的 实现,用于给Stream中元素做汇总的方法
	 */
	@Test
	public void test2() {
		List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
		Integer reduce = list.stream()
				.reduce(0, (x, y) -> x + y);
		System.out.println(reduce);//55

		Integer reduce1 = list.stream()
				.reduce(100, (x, y) -> x + y);
		System.out.println(reduce1);//155  //此处的reduce返回不是Optional  因为他有其起始值不可能为空

		//求所有员工工资的总和
		Optional<Double> reduce2 = emps.stream()
				.map(Employee::getSalary)
				.reduce(Double::sum);  //此处的reduce返回Optional  因为此结果有可能为空   Double.sum(double a, double b)为jdk1.8的新方法
		System.out.println(reduce2.get());

		//备注:map 和 reduce 的连接通常称为 map-reduce 模式,因 Google 用它 来进行网络搜索而出名。


		//将emps的名字收集到List中
		List<String> collect1 = emps.stream()
				.map(Employee::getName)
				.collect(Collectors.toList());
		System.out.println(collect1);

		String collect12 = emps.stream()
				.map(Employee::getName)
				.collect(Collectors.joining(",","【","}"));
		System.out.println(collect12);//【李四,张三,王五,赵六,赵六,赵六,田七}

		//将emps的名字收集到Set中
		Set<String> collect2 = emps.stream()
				.map(Employee::getName)
				.collect(Collectors.toSet());
		System.out.println(collect2);

		//将emps的名字收集到Set中
		Set<String> collect3 = emps.stream()
				.map(Employee::getName)
				.collect(Collectors.toCollection(HashSet::new));
		System.out.println(collect3);

		//计算总数
		Long collect4 = emps.stream()
				.collect(Collectors.counting());
		System.out.println(collect4);

		//计算所有工资平均值
		Double collect5 = emps.stream()
				.collect(Collectors.averagingDouble(Employee::getSalary));
		System.out.println(collect5);

		//所有员工总和
		Double collect6 = emps.stream()
				.collect(Collectors.summingDouble(Employee::getSalary));
		System.out.println(collect6);

		//员工工资最大值的员工信息
		Optional<Employee> collect7 = emps.stream()
				.collect(Collectors.maxBy((emp1, emp2) -> Double.compare(emp1.getSalary(), emp2.getSalary())));
		System.out.println(collect7);

		//员工工资最小值
		Optional<Double> max = emps.stream()
				.map(Employee::getSalary)//先获取所有的工资数
				.max(Double::compareTo);
		System.out.println(max.get());

		//获得所有员工信息中 工资 对应的组函数信息
		DoubleSummaryStatistics collect = emps.stream()
				.collect(Collectors.summarizingDouble(Employee::getSalary));
		System.out.println(collect);//DoubleSummaryStatistics{count=7, sum=48888.840000, min=3333.330000, average=6984.120000, max=9999.990000}
		System.out.println(collect.getSum());
		System.out.println(collect.getCount());
		System.out.println(collect.getAverage());
		System.out.println(collect.getMax());
		System.out.println(collect.getMin());

		//按照姓名分组
		Map<String, List<Employee>> collect8 = emps.stream()
				.collect(Collectors.groupingBy(Employee::getName));
		System.out.println(collect8);
		/*{
			李四 = [Employee[id = 102, name = 李四, age = 59, salary = 6666.66]],
			张三 = [Employee[id = 101, name = 张三, age = 18, salary = 9999.99]],
			王五 = [Employee[id = 103, name = 王五, age = 28, salary = 3333.33]],
			赵六 = [Employee[id = 104, name = 赵六, age = 8, salary = 7777.77],Employee[id = 104, name = 赵六, age = 8, salary = 7777.77],Employee[id = 104, name = 赵六, age = 8, salary = 7777.77]],
			田七 = [Employee[id = 105, name = 田七, age = 38, salary = 5555.55]]
		}*/


		//多级分组 先按照姓名分组,再按照年龄分组
		Map<String, Map<Integer, List<Employee>>> collect9 = emps.stream()
				.collect(Collectors.groupingBy(Employee::getName, Collectors.groupingBy(Employee::getAge)));
		System.out.println(collect9);
		/*{
			李四 = {
				59 = [Employee[id = 102, name = 李四, age = 59, salary = 6666.66]]
			}, 张三 = {
				18 = [Employee[id = 101, name = 张三, age = 18, salary = 9999.99]]
			}, 王五 = {
				28 = [Employee[id = 103, name = 王五, age = 28, salary = 3333.33]]
			}, 赵六 = {
				3 = [Employee[id = 104, name = 赵六, age = 3, salary = 7777.77]],
				8 = [Employee[id = 104, name = 赵六, age = 8, salary = 7777.77], Employee[id = 104, name = 赵六, age = 8, salary = 7777.77]]
			}, 田七 = {
				38 = [Employee[id = 105, name = 田七, age = 38, salary = 5555.55]]
			}
		  }
		*/

		//自定义分组
		Map<String, Map<String, List<Employee>>> collect11 = emps.stream()
				.collect(Collectors.groupingBy(Employee::getName, Collectors.groupingBy((emp) -> {
					if (((Employee) emp).getAge() <= 3) {
						return "婴儿";
					} else {
						return "少年";
					}
				})));
		System.out.println(collect11);
		/*{
			李四 = {
				少年 = [Employee[id = 102, name = 李四, age = 59, salary = 6666.66]]
			}, 张三 = {
				少年 = [Employee[id = 101, name = 张三, age = 18, salary = 9999.99]]
			}, 王五 = {
				少年 = [Employee[id = 103, name = 王五, age = 28, salary = 3333.33]]
			}, 赵六 = {
				婴儿 = [Employee[id = 104, name = 赵六, age = 3, salary = 7777.77]],
				少年 = [Employee[id = 104, name = 赵六, age = 8, salary = 7777.77], Employee[id = 104, name = 赵六, age = 8, salary = 7777.77]]
			}, 田七 = {
				少年 = [Employee[id = 105, name = 田七, age = 38, salary = 5555.55]]
			}
		  }
	    */



		//分区:满足条件的一个区  不满足条件的一个区
		Map<Boolean, List<Employee>> collect10 = emps.stream()
				.collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
		System.out.println(collect10);
		/*
			false = [Employee[id = 102, name = 李四, age = 59, salary = 6666.66],
			         Employee[id = 103, name = 王五, age = 28, salary = 3333.33],
			         Employee[id = 104, name = 赵六, age = 8, salary = 7777.77],
			         Employee[id = 104, name = 赵六, age = 3, salary = 7777.77],
			         Employee[id = 104, name = 赵六, age = 8, salary = 7777.77],
			         Employee[id = 105, name = 田七, age = 38, salary = 5555.55]],
			true = [Employee[id = 101, name = 张三, age = 18, salary = 9999.99]]
		}*/
	}

}

 

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