Java8新特性(三):Stream流与Stream API

Stream流简介

 Stream的操作步骤

1、创建Stream流

2、中间流水线操作

3、终止操作,产生需要的结果源数据

注意:Stream流和最终产生的结果不影响

创建Stream的代码示例

List<String> list = Arrays.asList("Sarah", "Terry", "Selina", "Tom");

// 创建Stream
@Test
public void test01(){
	// 1、通过Collection提供的stream()或者 paralleStream()
	Stream<String> stream01 =  list.stream();

	// 2、通过Stream类的静态方法of()
	Stream<String> stream02 = Stream.of("aa", "bb", "cc");

	// 3、通过Arrays的静态方法 stream() 获取数组流
	Stream<Integer> stream03 = Arrays.stream(new Integer[]{1,1,1});

	// 4、创建无限流
	Stream<Integer> stream04 = Stream.iterate(0,(x) -> x+2);
	stream04.limit(10).forEach(System.out::println);
}

 Stream的中间操作:筛选与切片

代码示例:

List<String> strList = Arrays.asList("Sarah", "Terry", "Selina", "Tom", "Selina", "Terry");

List<Employee> employeeList = Arrays.asList(
		new Employee("张三",18,2000),
		new Employee("李四",58,3000),
		new Employee("王五",48,7000),
		new Employee("陈六",38,9000),
		new Employee("田七",18,9000),
		new Employee("田七",18,9000),
		new Employee("田七",18,9000)
);

//中间操作
/**
 * 筛选与切片
 * filter:从流中排除某些元素
 * limit(n):从流中取不超过给n的元素
 * skip(n):返回一个去掉前n个元素的流,若流中元素不超过n,返回一个空流,与limit互补
 * distinct:根据hashCode()和equals()对元素去重
 */

// filter
@Test
public void test01(){
	// 中间操作
	Stream<String> stream = strList.stream().filter((x) -> x.length() > 3);

	// 终止操作
	stream.forEach(System.out::println);
}

// limit
@Test
public void test02(){
	employeeList.stream().limit(2).forEach(System.out::println);
}

// skip
@Test
public void test03(){
	employeeList.stream().skip(2).forEach(System.out::println);
}

// distinct
@Test
public void test04(){
	strList.stream().distinct().forEach(System.out::println);
}

// 惰性求值
@Test
public void test05(){
	employeeList.stream()
			.filter((x) -> {
				System.out.println("短路");
				return x.getAge() >50;
			})
			.limit(2)
			.forEach(System.out::println);
}

惰性求值

 

Stream的中间操作:映射

代码示例

List<String> strList = Arrays.asList("aa", "bb", "cc");

List<Employee> employeeList = Arrays.asList(
		new Employee("张三",18,2000),
		new Employee("李四",58,3000),
		new Employee("王五",48,7000),
		new Employee("陈六",38,9000),
		new Employee("田七",18,9000),
		new Employee("田七",18,9000),
		new Employee("田七",18,9000)
);

//中间操作
/**
 * 映射
 * map:接受Lamda,将元素转换成其他形式或提取信息。接受一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
 * flatMap:接收一个函数作为参数,将流中的每个值转换成另一个流,然后把所有的流连接成一个流
 * skip(n):
 * distinct:
 */

// map
@Test
public void test01(){
	employeeList.stream().map(e -> e.getName()).forEach(System.out::println);
}

// flatMap
@Test
public void test02(){
	strList.stream().map(s -> s.toUpperCase()).forEach(System.out::println);// {AA, BB, CC}
	strList.stream().flatMap(s -> filterCharacter(s)).forEach(System.out::println);// {a, a, b, b, c, c}
}

private Stream<Character> filterCharacter(String str){
	List<Character> list = new ArrayList<>();
	for (char c : str.toCharArray()) {
		list.add(c);
	}
	return list.stream();
}

  

Stream的中间操作:排序

代码示例

List<Employee> employeeList = Arrays.asList(
		new Employee("张三",18,2000),
		new Employee("李四",58,3000),
		new Employee("王五",48,7000),
		new Employee("陈六",38,9000),
		new Employee("田七",18,9000),
		new Employee("田七",18,9000),
		new Employee("田七",18,9000)
);

//中间操作
/**
 * 排序
 * sorted():自然排序
 * sorted(Comparactor com):定制排序
 */

// sorted()
@Test
public void test01(){
	employeeList.stream().map(e -> e.getAge()).sorted().forEach(System.out::println);
}

// sorted(Comparactor com)
@Test
public void test02(){
	employeeList.stream().sorted((e1, e2) -> {
	   if(e1.getAge() == e2.getAge()){
		   return e1.getName().compareTo(e2.getName());
	   }else {
		   return -Integer.compare(e1.getAge(), e2.getAge());
	   }
	}).forEach(System.out::println);
}

 

Stream的终止操作:查找与匹配

 代码示例:

List<Employee> employeeList = Arrays.asList(
		new Employee("张三",18,2000, Employee.Status.BUSY),
		new Employee("李四",58,3000, Employee.Status.FREE),
		new Employee("王五",48,7000, Employee.Status.VOCATION),
		new Employee("陈六",38,9000, Employee.Status.BUSY),
		new Employee("田七",18,9000, Employee.Status.BUSY),
		new Employee("王二",18,9000, Employee.Status.BUSY),
		new Employee("田七",18,9000, Employee.Status.VOCATION)
);

//终止操作
/**
 * 查找与匹配
 * allMatch():检查是否匹配所有元素
 * anyMatch():检查是否至少匹配一个元素
 * noneMatch():检查是否一个元素都没有匹配到
 * findFirst():返回第一个元素
 * findAny():返回任意一个元素
 * count():统计元素的总个数
 * max():返回流中的最大值
 * min():返回流中的最小值
 */

// allMatch()
@Test
public void test01(){
	boolean b = employeeList.stream().allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
	System.out.println(b);
}

// anyMatch()
@Test
public void test02(){
	boolean b = employeeList.stream().anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
	System.out.println(b);
}

// noneMatch()
@Test
public void test03(){
	boolean b = employeeList.stream().noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
	System.out.println(b);
}

// findFirst()
@Test
public void test04(){
	Optional<Employee> e =  employeeList.stream().findFirst();
	System.out.println(e.get());
}

// findAny()
@Test
public void test05(){
	// parallelStream为并行流
	Optional<Employee> employee =  employeeList.parallelStream().filter((e) -> e.getStatus().equals(Employee.Status.BUSY)).findAny();
	System.out.println(employee.get());

}

// count()
@Test
public void test06(){
	long count = employeeList.stream().count();
	System.out.println(count);
}

// max(Comparator com)
@Test
public void test07(){
	Optional<Employee> e =  employeeList.stream().max((e1, e2) -> {
		if(e1.getAge() == e2.getAge()){
			return e1.getName().compareTo(e2.getName());
		}else {
			return Integer.compare(e1.getAge(), e2.getAge());
		}
	});
	System.out.println(e.get());
}

// min(Comparator com)
@Test
public void test08(){
	Optional<Employee> e =  employeeList.stream().min((e1, e2) -> {
		if(e1.getAge() == e2.getAge()){
			return e1.getName().compareTo(e2.getName());
		}else {
			return Integer.compare(e1.getAge(), e2.getAge());
		}
	});
	System.out.println(e.get());
}

// 串行流与并行流
/**
 * 串行流:适合存在线程安全问题、阻塞任务、重量级任务,以及需要使用同一事务的逻辑。
 * 并行流:适合没有线程安全问题、较单纯的数据处理任务。
 */
@Test
public void test09(){
	List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
	numbers.stream().forEach(System.out::print);
	// 输出结果是固定的
	// 123456789

	numbers.parallelStream().forEach(System.out::print);
	// 输出结果是不固定的
	// 652879314

	//打印并查看线程信息
	numbers.parallelStream().forEach((num) -> System.out.println(Thread.currentThread().getName()+">>"+num));
	// ForkJoinPool.commonPool-worker-7>>3
	// ForkJoinPool.commonPool-worker-2>>4
	// ForkJoinPool.commonPool-worker-3>>9
	// ForkJoinPool.commonPool-worker-5>>2
	// ForkJoinPool.commonPool-worker-1>>7
	// ForkJoinPool.commonPool-worker-4>>5
	// ForkJoinPool.commonPool-worker-6>>8
	// main>>6
	// ForkJoinPool.commonPool-worker-7>>1
}

 

Stream的终止操作:归约 

代码示例:

List<Employee> employeeList = Arrays.asList(
		new Employee("张三",18,2000, Employee.Status.BUSY),
		new Employee("李四",58,3000, Employee.Status.FREE),
		new Employee("王五",48,7000, Employee.Status.VOCATION),
		new Employee("陈六",38,9000, Employee.Status.BUSY),
		new Employee("田七",18,9000, Employee.Status.BUSY),
		new Employee("王二",18,9000, Employee.Status.BUSY),
		new Employee("田七",18,9000, Employee.Status.VOCATION)
);

//终止操作
/**
 * 归约
 * reduce(T identity, BinaryOpertor) / reduce(BinaryOpertor) --可以将流中的元素反复结合起来,得到一个值
 *
 * map和reduce的连接通常被成为map-reduce模式,因Google用其来做网络搜索而出名
 */

// reduce()
@Test
public void test01(){
	List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
	Integer sum = list.stream().reduce(0, (x, y) -> x+y);
	System.out.println(sum);
	// reduce中的 x+y 的执行过程
	// 0+1=1
	// 1+2=3
	// 3+3=6
	// ...
	// 36+9=45
}

@Test
public void test02(){
	Optional<Integer> sum = employeeList.stream().map(e -> e.getAge()).reduce((x, y) -> x+y);
	System.out.println(sum.get());
}

Stream的终止操作:内部迭代

 Stream的终止操作:收集

 

Collector中的方法实现了对流的收集操作(如收集到List、Set、Map)。

Collectors实用类提供了很多静态方法,可以方便地创建收集器实例。

代码示例:

List<Employee> employeeList = Arrays.asList(
		new Employee("张三",18,2000, Employee.Status.BUSY),
		new Employee("李四",58,3000, Employee.Status.FREE),
		new Employee("王五",48,7000, Employee.Status.VOCATION),
		new Employee("陈六",38,9000, Employee.Status.BUSY),
		new Employee("田七",18,9000, Employee.Status.BUSY),
		new Employee("王二",18,9000, Employee.Status.BUSY),
		new Employee("田七",18,9000, Employee.Status.VOCATION)
);

//终止操作
/**
 * 收集
 * collector -- 将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法
 */

// reduce()
@Test
public void test01(){
	List<String > list = employeeList.stream().map(Employee::getName).collect(Collectors.toList());
	list.forEach(System.out::println);

	System.out.println("-----------------------");

	Set<String> set = employeeList.stream().map(Employee::getName).collect(Collectors.toSet());
	set.forEach(System.out::println);

	System.out.println("-----------------------");

	HashSet<String> hs = employeeList.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
	hs.forEach(System.out::println);
	//等同于以下的写法
	HashSet<String> hashSet = employeeList.stream().map(Employee::getName).collect(Collectors.toCollection(new Supplier<HashSet<String>>() {
		@Override
		public HashSet<String> get() {
			return new HashSet<>();
		}
	}));
	hashSet.forEach(System.out::println);
}

// 求和、求平均值、求最大值、求最小值
@Test
public void test02(){
	// 求所有age的平均值
	Double ave = employeeList.stream().collect(Collectors.averagingInt(Employee::getAge));

	// 求所有age的总和
	Integer sum = employeeList.stream().collect(Collectors.summingInt(Employee::getAge));

	// 求age最大的Employee
	Optional<Employee> max = employeeList.stream()
			.collect(Collectors.maxBy((o1, o2) -> Integer.compare(o1.getAge(), o2.getAge())));

	// 求age最小的Employee
	Optional<Employee> min = employeeList.stream().collect(Collectors.minBy((o1, o2) -> Integer.compare(o1.getAge(), o2.getAge())));
}

// 分组
@Test
public void test03(){
	Map<Employee.Status, List<Employee>> map = employeeList.stream().collect(Collectors.groupingBy(Employee::getStatus));
}

// 多级分组
@Test
public void test04(){
	Map<Employee.Status, Map<String, List<Employee>>> map = employeeList.stream().collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
		if(e.getAge() <= 35){
			return "青年";
		}else if((e.getAge() >= 35) &&  (e.getAge()<= 50)){
			return "中年";
		}else {
			return "老年";
		}
	})));
	System.out.println(map);
}

// 分区
@Test
public void test05(){
	Map<Boolean, List<Employee>> map = employeeList.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 8000));
	System.out.println(map);
}

@Test
public void test06(){
	DoubleSummaryStatistics dss = employeeList.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
	System.out.println(dss.getMax());
	System.out.println(dss.getAverage());
	System.out.println(dss.getMin());
	System.out.println(dss.getSum());
}

@Test
public void test07(){
	String str = employeeList.stream().map(Employee::getName).collect(Collectors.joining(",", "--", "++"));
	System.out.println(str);
}

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值