Java8新特性之Stream API

概述

       流(Stream):是数据渠道,用于操做数据源(集合、数组等)所生成的元素序列。java

      “集合讲的是数据,流讲的是计算”数组

StreamAPI特色

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

StreamAPI操做步骤

1. 建立Stream

//建立 Stream
	@Test
	public void test1(){
		//1.Collection 提供了两个方法  stream() 与 parallelStream()
		List<String> list = new ArrayList<>();
		Stream<String> stream1 = list.stream();

		//2.经过 Arrays 中的 stream() 获取一个数组流
		Employee[] employees = new Employee[10];
		Stream<Employee> stream2 = Arrays.stream(employees);

		//3. 经过 Stream 类中静态方法 of()
		List<String> list1 = Arrays.asList("12", "as", "df");
		Stream stream3 = Stream.of(list1);

		//4. 建立无限流
		//迭代
		Stream stream4 = Stream.iterate(1, x -> x + 2);
		stream4.limit(10).forEach(System.out::println);
		//生成
		Stream stream5 = Stream.generate(Math::random);
		stream5.limit(5).forEach(System.out::println);
	}

 

2. 一系列流水史的中间操做

多个中间操做能够链接起来造成一个流水线,除非流水线上触发终止操做,不然中间操做不会执行任何的处理!而在终止操做时一次性所有处理,称为“惰性求值”ide


① 筛选与切片

方法 描述
filter(Predicate p) 接收Lambda ,从流中排除某些元素
distinct() 筛选,经过流所生成元素的hashCode() 和equals() 去除重复元素
limit(long maxSize) 截断流,使其元素不超过给定数量
skip(long n) 跳过元素,返回一个扔掉了前n 个元素的流。若流中元素不足n 个,则返回一个空流。与limit(n) 互补
//2. 中间操做
	List<Employee> employees = Arrays.asList(
			new Employee("张三", 20),
			new Employee("李四", 50),
			new Employee("王五", 40),
			new Employee("王五", 40),
			new Employee("王五", 40),
			new Employee("赵六", 10),
			new Employee("王琦", 8),
			new Employee("李逵", 4)
	);

	/**
	 * 筛选与切片
	 * filter(Predicate p) :接收Lambda ,从流中排除某些元素。
	 * distinct() :筛选,经过流所生成元素的hashCode() 和equals() 去除重复元素
	 * limit(long maxSize):截断流,使其元素不超过给定数量。
	 * skip(long n):跳过元素,返回一个扔掉了前n 个元素的流。若流中元素不足n 个,则返回一个空流。与limit(n) 互补
	 */
	//内部迭代:由StreamAPI本身完成
	//filter(Predicate p) :接收Lambda ,从流中排除某些元素。
	@Test
	public void test2() {
		/*多个中间操做能够链接起来造成一个流水线,除非流水
		线上触发终止操做,不然中间操做不会执行任何的处理!
		而在终止操做时一次性所有处理,称为“惰性求值”*/
		//中间操做:不会执行任何操做
		Stream<Employee> s = employees.stream().filter((e) -> {
			System.out.println("Stream API中间操做!");
			return e.getAge() > 25;
		});
		//终止操做:一次性操做所有操做
		s.forEach(System.out:: println);
	}

	//外部迭代
	@Test
	public void test3() {
		Iterator<Employee> it = employees.iterator();
		while (it.hasNext()) {
			Employee next = it.next();
			System.out.println(next);
		}
	}

	//limit(long maxSize):截断流,使其元素不超过给定数量。
	@Test
	public void test4() {
		employees.stream()
				.filter(e -> e.getAge() > 30)
				.limit(3)
				.forEach(System.out:: println);
		//运行结果
		/*Employee{name='李四', age=50}
		Employee{name='王五', age=40}
		Employee{name='王五', age=40}*/
	}

	//skip(long n):跳过元素,返回一个扔掉了前n 个元素的流。若流中元素不足n 个,则返回一个空流。与limit(n) 互补
	@Test
	public void test5() {
		employees.stream()
				.filter(e -> e.getAge() > 30)
				.skip(1)
				.forEach(System.out:: println);
		//运行结果
		/*Employee{name='王五', age=40}
		Employee{name='王五', age=40}
		Employee{name='王五', age=40}*/
	}

	//distinct() :筛选,经过流所生成元素的hashCode() 和equals() 去除重复元素
	@Test
	public void test6() {
		employees.stream()
				.filter(e -> e.getAge() > 30)
				.distinct()
				.forEach(System.out:: println);
		//运行结果
		/*Employee{name='李四', age=50}
		  Employee{name='王五', age=40}*/
	}

②映射

方法    描述
map(Functionf) 接收一个函数做为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素
mapToDouble(ToDoubleFunction f) 接收一个函数做为参数,该函数会被应用到每一个元素上,产生一个新的DoubleStream
mapToInt(ToIntFunction f) 接收一个函数做为参数,该函数会被应用到每一个元素上,产生一个新的IntStream
mapToLong(ToLongFunction f) 接收一个函数做为参数,该函数会被应用到每一个元素上,产生一个新的LongStream
flatMap(Function f) 接收一个函数做为参数,将流中的每一个值都换成另外一个流,而后把全部流链接成一个流
/**
	 * 映射
	 * map(Functionf) :接收一个函数做为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素。
	 * mapToDouble(ToDoubleFunction f) :接收一个函数做为参数,该函数会被应用到每一个元素上,产生一个新的DoubleStream。
	 * mapToInt(ToIntFunction f) :接收一个函数做为参数,该函数会被应用到每一个元素上,产生一个新的IntStream。
	 * mapToLong(ToLongFunction f) :接收一个函数做为参数,该函数会被应用到每一个元素上,产生一个新的LongStream。
	 * flatMap(Function f) :接收一个函数做为参数,将流中的每一个值都换成另外一个流,而后把全部流链接成一个流
	 */
	@Test
	public void test7() {
		//map(Functionf) :接收一个函数做为参数,该函数会被应用到每一个元素上,并将其映射成一个新的元素。
		List<String> list = Arrays.asList("aaa", "bbb", "ccc");
		list.stream()
				.map(str -> str.toUpperCase())
				.forEach(System.out:: print);//AAABBBCCC

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

		employees.stream()
				.map(Employee:: getName)
				.forEach(System.out:: print);//张三李四王五王五王五赵六王琦李逵

		System.out.println("-------------------------");
		//mapToInt(ToIntFunction f) :接收一个函数做为参数,该函数会被应用到每一个元素上,产生一个新的IntStream。
		IntStream is = employees.stream()
								.mapToInt(Employee:: getAge);
		is.forEach(System.out::println);

		System.out.println("-------------------------");
		//flatMap(Function f) :接收一个函数做为参数,将流中的每一个值都换成另外一个流,而后把全部流链接成一个流
		list.stream()
				.flatMap(TestStreamAPI1:: filterCharacter)
				.forEach(System.out:: println);

	}

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

③排序

方法 描述
sorted() 产生一个新流,其中按天然顺序排序
sorted(Comparator comp) 产生一个新流,其中按比较器顺序排序
/**
	 * 排序
	 * sorted() 产生一个新流,其中按天然顺序排序(Comparable)
	   sorted(Comparator comp) 产生一个新流,其中按比较器顺序排序(	Comparator)
	 */
	@Test
	public void test8(){
		//sorted() 产生一个新流,其中按天然顺序排序(Comparable)
		List<String> list = Arrays.asList("aaa", "eee", "ccc","yyy");
		list.stream()
				.sorted()
				.forEach(System.out::print);//aaaccceeeyyy

		System.out.println("-----------------");
		//sorted(Comparator comp) 产生一个新流,其中按比较器顺序排序(	Comparator)
		employees.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);
	}

3. 终止操做

①查找与匹配

方法 描述
allMatch(Predicate p) 检查是否匹配全部元素
anyMatch(Predicate p) 检查是否至少匹配一个元素
noneMatch(Predicatep) 检查是否没有匹配全部元素
findFirst() 返回第一个元素
findAny() 返回当前流中的任意元素
count() 返回流中元素总数
max(Comparator c) 返回流中最大值
min(Comparator c) 返回流中最小值
forEach(Consumer c) 内部迭代(使用Collection 接口须要用户去作迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代作了)
/**
	 * 查找与匹配
	 * allMatch(Predicate p) 检查是否匹配全部元素
	 anyMatch(Predicate p) 检查是否至少匹配一个元素
	 noneMatch(Predicatep) 检查是否没有匹配全部元素
	 findFirst() 返回第一个元素
	 findAny() 返回当前流中的任意元素
	 count() 返回流中元素总数
	 max(Comparator c) 返回流中最大值
	 min(Comparator c) 返回流中最小值
	 forEach(Consumer c) 内部迭代(使用Collection 接口须要用户去作迭代,称为外部迭代。相反,Stream API 使用内部迭代——它帮你把迭代作了)
	 */
	@Test
	public void test9(){
		boolean b1 = employees.stream()
				.allMatch(e -> e.getAge() > 20);
		System.out.println(b1);//false

		boolean b2 = employees.stream()
				.anyMatch(e -> e.getAge() > 20);
		System.out.println(b2);//true

		boolean b3 = employees.stream()
				.noneMatch(e -> e.getAge() > 20);
		System.out.println(b3);//false

		Optional<Employee>  op1 = employees.stream()
				.findFirst();
		System.out.println(op1.get());//Employee{name='张三', age=20}
		//并行流与串行流
		/*并行流就是把一个内容分红多个数据块,并用不一样的线程分别处理每一个数据块的流。
		Java 8 中将并行进行了优化,咱们能够很容易的对数据进行并行操做。
		Stream API 能够声明性地经过parallel() 与sequential() 在并行流与顺序流之间进行切换。*/
		Optional<Employee> op2 = employees.stream().parallel()
				.findAny();
		System.out.println(op2.get());//Employee{name='赵六', age=10}
		Optional<Employee> op3 = employees.stream().sequential()
				.findAny();
		System.out.println(op3.get());//Employee{name='张三', age=20}

		long num = employees.stream()
				.count();
		System.out.println(num);//8

		Optional<Employee> op4 = employees.stream()
				.max(Comparator.comparingInt(Employee:: getAge));
		System.out.println(op4.get());//Employee{name='李四', age=50}

		Optional<Employee> op5 = employees.stream()
				.min(Comparator.comparingInt(Employee:: getAge));
		System.out.println(op5.get());//Employee{name='李逵', age=4}
	}

②归约

方法 描述
reduce(T iden, BinaryOperator b) 能够将流中元素反复结合起来,获得一个值。返回T
reduce(BinaryOperator b) 能够将流中元素反复结合起来,获得一个值。返回Optional<T>
/**
	 * 归约
	 * reduce(T iden, BinaryOperator b) 能够将流中元素反复结合起来,获得一个值。返回T
	 reduce(BinaryOperator b) 能够将流中元素反复结合起来,获得一个值。返回Optional<T>
	 */
	@Test
	public void test10(){
		List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
		Integer sum = list.stream()
				.reduce(0, (x, y) -> x + y);
		System.out.println(sum); //21

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

		Optional<Integer> op = employees.stream()
				.map(Employee:: getAge)
				.reduce(Integer:: sum);
		System.out.println(op.get());//212
	}

③收集

方法 描述
collect(Collector c) 将流转换为其余形式。接收一个Collector接口的
实现,用于给Stream中元素作汇总的方法

Collector 接口中方法的实现决定了如何对流执行收集操做(如收集到List、Set、Map)。可是Collectors 实用类提供了不少静态方法,能够方便地建立常见收集器实例,具体方法与实例以下表:函数

方法   返回类型 做用
toList List<T> 把流中元素收集到List
List<Employee>emps=list.stream().collect(Collectors.toList());
toSet Set<T> 把流中元素收集到Set
Set<Employee>emps=list.stream().collect(Collectors.toSet());
toCollection Collection<T> 把流中元素收集到建立的集合
Collection<Employee>emps=list.stream().collect(Collectors.toCollection(ArrayList::new));
counting Long 计算流中元素的个数
long count=list.stream().collect(Collectors.counting());
summingInt Integer 对流中元素的整数属性求和
inttotal=list.stream().collect(Collectors.summingInt(Employee::getSalary));
averagingInt Double 计算流中元素Integer属性的平均值
doubleavg=list.stream().collect(Collectors.averagingInt(Employee::getSalary));
summarizingInt IntSummaryStatistics 收集流中Integer属性的统计值。如:平均值
IntSummaryStatisticsiss=list.stream().collect(Collectors.summarizingInt(Employee::getSalary));
joining String 链接流中每一个字符串
Stringstr=list.stream().map(Employee::getName).collect(Collectors.joining());
maxBy Optional<T> 根据比较器选择最大值
Optional<Emp>max=list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
minBy Optional<T> 根据比较器选择最小值
Optional<Emp>min=list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));
reducing 归约产生的类型 从一个做为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值
inttotal=list.stream().collect(Collectors.reducing(0,Employee::getSalar,Integer::sum));
collectingAndThen 转换函数返回的类型 包裹另外一个收集器,对其结果转换函数
inthow=list.stream().collect(Collectors.collectingAndThen(Collectors.toList(),List::size));
groupingBy Map<K,List<T>> 根据某属性值对流分组,属性为K,结果为V
Map<Emp.Status, List<Emp>> map= list.stream().collect(Collectors.groupingBy(Employee::getStatus));
partitioningBy Map<Boolean,List<T>> 根据true或false进行分区
Map<Boolean,List<Emp>>vd=list.stream().collect(Collectors.partitioningBy(Employee::getManage));
/**
	 * 收集
	 * collect(Collector c) 将流转换为其余形式。接收一个Collector接口实现,用于给Stream中元素作汇总的方法
	 */
	@Test
	public void test11(){
		List<String> list = employees.stream()
				.map(Employee:: getName)
				.collect(Collectors.toList());
		list.forEach(System.out::print);//张三李四王五王五王五赵六王琦李逵

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

		Set<String> set = employees.stream()
				.map(Employee:: getName)
				.collect(Collectors.toSet());
		set.forEach(System.out::print);//李四张三王琦王五赵六李逵

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

		HashSet hset = employees.stream()
				.map(Employee:: getName)
				.collect(Collectors.toCollection(HashSet::new));
		hset.forEach(System.out::print);//李四张三王琦王五赵六李逵
	}

	@Test
	public void test12(){
		//总数
		long count = employees.stream()
							.collect(Collectors.counting());
		System.out.println(count);//8
		//平均值
		Double avg = employees.stream()
				.collect(Collectors.averagingInt(Employee::getAge));
		System.out.println(avg);//26.5

		//总和
		int sum = employees.stream()
							.collect(Collectors.summingInt(Employee:: getAge));
		System.out.println(sum);//212
		//最大值
		Optional<Employee> max = employees.stream()
				.collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())));
		System.out.println(max.get());//Employee{name='李四', age=50}
		//最小值
		Optional<Integer> min = employees.stream()
				.map(Employee:: getAge)
				.collect(Collectors.minBy(Integer:: compare));
		System.out.println(min.get());//4
	}
    //分组
	@Test
	public void test13(){
		Map<String,List<Employee>> map = employees.stream()
				.collect(Collectors.groupingBy(Employee:: getName));
		System.out.println(map.toString());
		/*{李四=[Employee{name='李四', age=50}],
		 张三=[Employee{name='张三', age=20}],
		 王琦=[Employee{name='王琦', age=8}],
		 王五=[Employee{name='王五', age=40}, Employee{name='王五', age=40}, Employee{name='王五', age=40}],
		 赵六=[Employee{name='赵六', age=10}],
		 李逵=[Employee{name='李逵', age=4}]}*/
	}

	//分区
	@Test
	public void test14() {
		Map<Boolean, List<Employee>> map = employees.stream()
				.collect(Collectors.partitioningBy((e) ->e.getAge() > 30));
		System.out.println(map);
		/*{
		false=[Employee{name='张三', age=20},
		       Employee{name='赵六', age=10},
		       Employee{name='王琦', age=8},
		       Employee{name='李逵', age=4}],
		 true=[Employee{name='李四', age=50},
		       Employee{name='王五', age=40},
		       Employee{name='王五', age=40},
		       Employee{name='王五', age=50}]}*/
	}

	//summarizingInt IntSummaryStatistics 收集流中Integer属性的统计值。如:平均值
	@Test
	public void test15(){
		DoubleSummaryStatistics ds = employees.stream()
				.collect(Collectors.summarizingDouble(Employee:: getAge));
		System.out.println(ds.getAverage());//27.75
		System.out.println(ds.getCount());//8
		System.out.println(ds.getMax());//50.0
		System.out.println(ds.getMin());//4.0
		System.out.println(ds.getSum());//222.0
	}

	//joining链接流中每一个字符串
	@Test
	public void test16(){
		String str = employees.stream()
				.map(Employee:: getName)
				.collect(Collectors.joining(",", "---", "==="));
		System.out.println(str);//---张三,李四,王五,王五,王五,赵六,王琦,李逵===
	}
相关文章
相关标签/搜索