Java8新特性

您所在的位置:网站首页 tara年龄最大 Java8新特性

Java8新特性

2024-07-13 22:43| 来源: 网络整理| 查看: 265

代码托管:https://github.com/stopping5/javaBase/blob/master/src/com/company/java8/StreamTest.java

一、什么是Stream 1、定义

​ Java 8引入了一套新的类库,位于包java.util.stream下,称为Stream API。这套API操作数据的思路不同于我们之前介绍的容器类API,它们是函数式的,非常简洁、灵活、易读。

A sequence of elements supporting sequential and parallel aggregate operations.

​ 支持顺序和并行聚合操作的元素序列。

​ 在java8中java.util.Collection新增了两个默认方法,它们可以返回一个Stream。顺序流就是由一个线程执行操作。而并行流背后可能有多个线程并行执行。

//通过该集合返回集合源的流 default Stream stream() //通过该集合返回并行的流 default Stream parallelStream() 2、Stream特性 Stream不会存储元素Stream不改变源对象,会根据相关操作返回一个持有结果的新对象Stream 操作是延迟执行的,意味着等待结果的时候才执行。 二、创建Stream

​ 通过集合、数组创建一个数据源。

通过 java.util.Collection.stream() 方法用集合创建流 List list = Arrays.asList("a", "b", "c"); // 创建一个顺序流 Stream stream = list.stream(); // 创建一个并行流 Stream parallelStream = list.parallelStream(); 使用java.util.Arrays.stream(T[] array)方法用数组创建流 int[] array={1,3,5,6,8}; IntStream stream = Arrays.stream(array); 使用Stream的静态方法:of()、iterate()、generate() Stream stream = Stream.of(1, 2, 3, 4, 5, 6); Stream stream2 = Stream.iterate(0, (x) -> x + 3).limit(4); stream2.forEach(System.out::println); // 0 2 4 6 8 10 Stream stream3 = Stream.generate(Math::random).limit(3); stream3.forEach(System.out::println); 三、中间操作

​ 中间操作的目的主要是对数据进行操作,例如映射、统计、过滤等…

1、筛选操作 Filter

返回predicate匹配的流

Stream filter(Predicate predicate) 案例:筛选年龄大于18并且薪资大于8000的员工 private static void filterDemo(List employees) { employees.stream() //年龄大于18 .filter((e)->{ System.out.println("筛选大于18"); return e.getAge() > 18; }) //并且薪资大于8000 .filter((e)->{ System.out.println("筛选大于8000"); return e.getSalary() > 8000; }) .limit(2)//&& 操作 .forEach( (e)->{ System.out.println(e.toString()); } ); //筛选大于18 //筛选大于18 //筛选大于18 //筛选大于8000 //Employee{name='张5', age=28, salary=18000.0} //筛选大于18 //筛选大于8000 //Employee{name='张6', age=19, salary=8400.0} } 2、映射操作 - Map

接收lambda,将元素转换成其他形式和提取信息。接收一个函数作为参数,该函数会被应用到每个元素上。相当于数据库中提取一列的数据。

Stream map(Function mapper) ------------------------------------------------------------ Type Parameters: R - The element type of the new stream Parameters: mapper - a non-interfering, stateless function to apply to each element Returns: the new stream

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vY8vZVQi-1625380843937)(http://img.stopping.top/20210704123510.svg)]

类似的还有:mapToInt、mapToLong、mapToDouble

案例:在Employee获取所有年龄组成新的流。

这里通过employee.getAge()函数应用到每个元素上的结果。

private static void mapDemo(List employees) { employees.stream().map(Employee::getAge).forEach(System.out::println); } //18 - 13 - 28 - 19 - 38 - 15 - 22 - FlatMap

接收一个函数作为参数,将流中每个值都换成另外一个流,然后把所有流连接成一个流。

Stream flatMap(Function mapper)----------------------------------------------------------Type Parameters: R - The element type of the new streamParameters: mapper - a non-interfering, stateless function to apply to each element which produces a stream of new valuesReturns: the new stream 案例

将流中的每个字符串输出为字符。在FlatMap中直接就可以将每个元素的值转化为一个流。在Map中通过调用flatMapStringToChar()将元素转化为流,通过Stream相当于{{a,a,a},{b,b,b},{c,c,c}},而flatMap{a,a,a,b,b,b,c,c,c}两者里面的数据结构不一样。

private static void flatMapDemo() { System.out.println("Map实现···"); List s = Arrays.asList("aaa","bbb","ccc"); //map实现每个元素字符串转化为字符流输出 Stream ssc = s.stream().map(StreamTest::flatMapStringToChar); ssc.forEach((sc)->{ sc.forEach(System.out::println); }); System.out.println("flatMap实现···"); //flatMap 实现每个元素字符串转化为字符流输出 s.stream().flatMap(StreamTest::flatMapStringToChar).forEach(System.out::println); } public static Stream flatMapStringToChar(String s){ List lc = new ArrayList(); for (Character c : s.toCharArray()){ lc.add(c); } return lc.stream(); } //Map实现··· //a //a //a //b //b //b //c //c //c //flatMap实现··· //a //a //a //b //b //b //c //c //c 3、切片操作 limit 截取

限制返回长度不超过maxSize的流

Stream limit(long maxSize) ------------------------------------------------------------------- Parameters: maxSize - the number of elements the stream should be limited to Returns: the new stream skip 丢弃

丢弃流中前 n 个元素,如果丢弃的元素大于流的本身的元素则返回一个空流。

Stream skip(long n)--------------------------------------------------------------------Parameters: n - the number of leading elements to skipReturns: the new stream distinct 去重

去重,返回流中不同的元素(根据 Object.equals(Object))流

Stream distinct()-----------------------------------------------------------------Returns: the new stream 案例 //传入数据static List getEmployees(){ Employee e1 = new Employee("张3",18,8000.00); Employee e2 = new Employee("张4",13,8011.00); Employee e3 = new Employee("张5",28,18000.00); Employee e4 = new Employee("张6",19,8400.00); Employee e5 = new Employee("张7",38,7000.00); Employee e6 = new Employee("张8",15,8200.00); Employee e7 = new Employee("张9",22,9000.00); Employee e9 = new Employee("张9",22,9000.00); Employee e8 = new Employee("张9",22,9000.00); return Arrays.asList(e1,e2,e3,e4,e5,e6,e7);}private static void limitAndSkipDemo(List employees) { System.out.println("获取前4条数据"); employees.stream().limit(4).forEach(System.out::println); System.out.println("跳过前4条数据"); employees.stream().skip(4).forEach(System.out::println); //去重-筛选员工姓名之后去重复 employees.stream().map(Employee::getName).distinct().forEach(System.out::println); //张3 //张4 //张5 //张6 //张7 //张8 //张9}//获取前4条数据//Employee{name='张3', age=18, salary=8000.0}//Employee{name='张4', age=13, salary=8011.0}//Employee{name='张5', age=28, salary=18000.0}//Employee{name='张6', age=19, salary=8400.0}//跳过前4条数据//Employee{name='张7', age=38, salary=7000.0}//Employee{name='张8', age=15, salary=8200.0}//Employee{name='张9', age=22, salary=9000.0} 4、收集操作

四、终端操作

​ 中间操作不触发实际的执行,返回值是Stream,而终端操作触发执行,返回一个具体的值,除了collect, Stream API的终端操作还有max、min、count、allMatch、anyMatch、noneMatch、findFirst、findAny、forEach、toArray、reduce等

MAX、MIN Optional max(Comparator comparator)Optional min(Comparator comparator)-------------------------------------------------Parameters: comparator - a non-interfering, stateless Comparator to compare elements of this streamReturns: an Optional describing the maximum/minimum element of this stream, or an empty Optional if the stream is empty 案例:获取最大/最小年龄的员工信息 private static void maxMinDemo(List employees) { Employee maxAgeEmployee = employees.stream().max(Comparator.comparing(Employee::getAge)).get(); System.out.println("maxAgeEmployee:"+maxAgeEmployee.toString()); Employee minAgeEmployee = employees.stream().min(Comparator.comparing(Employee::getAge)).get(); System.out.println("minAgeEmployee"+minAgeEmployee.toString()); //maxAgeEmployee:Employee{name='张7', age=38, salary=7000.0} //minAgeEmployeeEmployee{name='张4', age=13, salary=8011.0}} Count

返回流中元素的个数

private static void countDemo(List employees) { System.out.println("employee个数:"+ employees.stream().count()); //employee个数:9 } allMatch/anyMatch/noneMatch

这几个函数都接受一个谓词Predicate,返回一个boolean值,用于判定流中的元素是否满足一定的条件。

boolean anyMatch(Predicate predicate)boolean allMatch(Predicate predicate)boolean noneMatch(Predicate predicate)

它们的区别是:

allMatch:只有在流中所有元素都满足条件的情况下才返回true。anyMatch:只要流中有一个元素满足条件就返回true。noneMatch:只有流中所有元素都不满足条件才返回true。

如果流为空,那么这几个函数的返回值都是true。

private static void match(List employees) { System.out.println("是否所有员工都大于18岁:"+ employees.stream().allMatch(e->e.getAge()>18)); System.out.println("是否所有员工都大于10岁:"+ employees.stream().allMatch(e->e.getAge()>10)); System.out.println("是否有员工22岁:"+ employees.stream().anyMatch(e->e.getAge()==22)); //是否所有员工都大于18岁:false //是否所有员工都大于10岁:true //是否有员工22岁:true } findFirst/findAny Optional findFirst()返回流的第一个元素的 Optional,如果流为空,则返回空的 Optional。Optional findAny()返回流的某些元素的 Optional,如果流为空,则返回空的 Optional。-------------------------------------------------------------------Returns: an Optional describing some element of this stream, or an empty Optional if the stream is emptyThrows: NullPointerException - if the element selected is null private static void find(List employees) { Employee employee = employees.stream().findFirst().get(); System.out.println("first employee:"+employee); Employee employee1 = employees.stream().findAny().get(); System.out.println("any employee:"+employee1); //first employee:Employee{name='张3', age=18, salary=8000.0} //any employee:Employee{name='张3', age=18, salary=8000.0} } foreach

​ 遍历流中的元素,foreach和佛reachOrdered的区别:在并行流中,forEach不保证处理的顺序,而forEachOrdered会保证按照流中元素的出现顺序进行处理。

void forEach(Consumer action)void forEachOrdered(Consumer action) reduce

​ reduce代表归约或者叫折叠,它是max/min/count的更为通用的函数,将流中的元素归约为一个值。例如例如 sum()、max() 或 count()都是归约函数。

T reduce(T identity, BinaryOperator accumulator)//相当于T result = identity;for (T element : this stream) result = accumulator.apply(result, element) return result;---------------------------------------------------------------------Optional reduce(BinaryOperator accumulator)//相当于boolean foundAny = false;T result = null;for (T element : this stream) { if (!foundAny) { foundAny = true; result = element; } else result = accumulator.apply(result, element);}return foundAny ? Optional.of(result) : Optional.empty();----------------------------------------------------------------------- U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)//相当于U result = identity;for (T element : this stream) result = accumulator.apply(result, element) return result; Collectors

​ java.util.stream.Collectors 实现了Collector接口,提供了很多有用的归约操作,例如将中间操作累积为集合、连接数据、分组、统计等。

list.steam().collction(Collectors)

用法示例:

// Accumulate names into a ListList list = people.stream().map(Person::getName).collect(Collectors.toList());// Accumulate names into a TreeSetSet set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));// Convert elements to strings and concatenate them, separated by commasString joined = things.stream() .map(Object::toString) .collect(Collectors.joining(", "));// Compute sum of salaries of employeeint total = employees.stream() .collect(Collectors.summingInt(Employee::getSalary)));// Group employees by departmentMap byDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment));// Compute sum of salaries by departmentMap totalByDept = employees.stream() .collect(Collectors.groupingBy(Employee::getDepartment, Collectors.summingInt(Employee::getSalary)));// Partition students into passing and failingMap passingFailing = students.stream() .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD)); groupingBy 分组

​ 分组类似于数据库查询语言SQL中的group by语句,它将元素流中的每个元素分到一个组,可以针对分组再进行处理和收集。

public static Collector groupingBy(Function classifier)----------------------------------------------------------------将数据分组,分组关键字存在在集合中,数据保存在Map{ System.out.println("age:"+i+","+"user:"+user.toString()); });}

结果

age:18,user:[User{username='tom', age=18, phone='13141234567'}, User{username='gogo', age=18, phone='13141234567'}]age:20,user:[User{username='job', age=20, phone='13141234567'}]

使用Stream group方法等同于下面方法实现,很显然Steam Group更加的简洁。

/** * 非Stream group 实现 * */private static void userGroup(List users) { Map userMap = new HashMap(); for (User u : users){ Integer age = u.getAge(); if (userMap.containsKey(age)){ userMap.get(age).add(u); }else{ List user = new ArrayList(); user.add(u); userMap.put(age,user); } } userMap.forEach((i,user)->{ System.out.println("age:"+i+","+"user:"+user.toString()); });}


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3