首页 > 其他分享 >JDK1.8新特性

JDK1.8新特性

时间:2023-02-19 00:12:47浏览次数:54  
标签:JDK1.8 stream Stream System 特性 50 println out

JDK1.8新特性

1、Lambda表达式

2、::运算符引用方法

3、stream

Stream是JDK1.8新增的一个特性,称之为Stream,它可以给予Lamdba表达式对集合数据进行处理(如:遍历、排序、去重、修改)等操作,并且支持同时使用2种或以上的操作。

Stream流是从支持数据处理操作的源生成的元素序列,源可以是数组、文件、集合、函数。流不是集合元素,它不是数据结构并不保存数据,它的主要目的在于计算。

3.1、创建Stream

3.1.1、使用Stream提供的方法创建

3.1.1.1、of方法创建
// 不仅可以使用int,也可以是对象、Map、Object。。。。
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
// 使用对象创建
Stream<Person> integerStream = Stream.of(person1, person2);
3.1.1.2、iterate方法创建

iterate的第一个参数为n的值,第二个参数是一个lambda表达式,返回一个值提供给Stream,由于这个流是无限的,所以需要使用limit方法进行截取,这个方法的具体用法可以参考3.2.5。

Stream<Integer> limit = Stream.iterate(1, n -> n + 2).limit(5);
3.1.1.3、generator方法创建

generator方法和iterate类似,只是lambda表达式的类型不一样,它的lambda表达式没有参数,只有返回值。这个流也是无限的,所以需要使用limit方法进行截取,这个方法的具体用法可以参考3.2.5。

Stream<Double> limit = Stream.generate(() -> Math.floor(Math.random() * 100)).limit(10);

3.1.2、使用集合创建

// 使用of方法创建
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
integers.add(4);
integers.add(5);
Stream<Integer> interStream = integers.stream();

3.1.3、使用Array创建

// 使用of方法创建
Integer[] integerArray = {1,3,5,7,9};
Stream<Integer> stream = Arrays.stream(integerArray);

3.1.4、使用文件创建

通过Files.line方法得到一个流,并且得到的每个流是给定文件中的一行

try {
  Stream<String> fileStream = Files.lines(Paths.get("data.txt"), Charset.defaultCharset());
} catch (IOException e) {
  e.printStackTrace();
}

3.2、中间操作符

通常对于Stream的中间操作,可以视为是源的查询,并且是懒惰式的设计,对于源数据进行的计算只有在需要时才会被执行,与数据库中视图的原理相似;

Stream流的强大之处便是在于提供了丰富的中间操作,相比集合或数组这类容器,极大的简化源数据的计算复杂度

一个流可以跟随零个或多个中间操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用

这类操作都是惰性化的,仅仅调用到这类方法,并没有真正开始流的遍历,真正的遍历需等到终端操作时,常见的中间操作有下面即将介绍的 filter、map 等

3.2.1、filter方法

通过设置的条件过滤元素

// 创建stream,生成十个100以内的随机数填充
Stream<Double> stream = Stream.generate(() -> Math.floor(Math.random() * 100)).limit(10);
// 先筛选大于50的,再进行遍历
stream.filter(v->v>50).forEach(System.out::println);

打印结果:

76.0
75.0
71.0
90.0
81.0

可以看到,原本十个随机数经过过滤后只剩下五个大于50的~

3.2.2、map方法

map元素可以对集合进行遍历,并且对每个元素进行修改后返回一个新的stream

// 创建stream,生成十个100以内的随机数填充
Stream<Double> stream = Stream.generate(() -> Math.floor(Math.random() * 100)).limit(10);
// 先筛选大于50的,再把这部分数据都加上50
stream.filter(v->v>50).map(v->v+50).forEach(System.out::println);

打印结果:

125.0
144.0
105.0
146.0
119.0
149.0

从上面的结果可以看出,stream的方法是有顺序的,其实是一个链式调用,先对结果进行flter返回一个新的stream,再对这个新的stream修改后返回一个新的stream。

调换fiter和map的顺序再次执行

// 创建stream,生成十个100以内的随机数填充
Stream<Double> stream = Stream.generate(() -> Math.floor(Math.random() * 100)).limit(10);
// 先筛选大于50的,再把这部分数据都加上50
stream.map(v->v+50).filter(v->v>50).forEach(System.out::println);

输出结果:

72.0
105.0
115.0
128.0
129.0
128.0
78.0
68.0
134.0
51.0

3.2.3、distinct方法

这个方法如单词含义一样,是用来去重的。对于Object的子类,是根据元素的hashCode和equels方法来实现的对比。所以要根据使用场景重写这两个方法。

// 创建stream,生成十个100以内的随机数填充
Stream<Double> stream = Stream.generate(() -> Math.floor(Math.random() * 2)).limit(10);
// 先筛选大于50的,再把这部分数据都加上50
stream.map(v->v+50).filter(v->v>=50).distinct().forEach(System.out::println);

输出结果:

51.0
50.0

3.2.4、sorted方法

此方法用来排序,返回排序后的流。

// 创建stream,生成十个100以内的随机数填充
Stream<Double> stream = Stream.generate(() -> Math.floor(Math.random() * 2)).limit(10);
// 先筛选大于50的,再把这部分数据都加上50
stream.map(v->v+50).filter(v->v>=50).distinct().sorted().forEach(System.out::println);

输出:

50.0
51.0

从运行结果可以看出它默认采取的是升序排序,如果想自定义查询规则,也可以调用sorted的重载方法,传递一个Comparator Lambda表达式。

// 创建stream,生成十个100以内的随机数填充
Stream<Double> stream = Stream.generate(() -> Math.floor(Math.random() * 5)).limit(10);
// 先筛选大于50的,再把这部分数据都加上50
stream.map(v->v+50).filter(v->v>=50).distinct().sorted((o1,o2)-> (int)Math.round(o2-o1)).forEach(System.out::println);

输出:

54.0
53.0
52.0
51.0
50.0

3.2.5、limit方法

会返回一个不超过给定长度的流,实际上我们上面的案例都已经用过这个方法了,下面再次演示一下limit“截取”流。

Stream.of(1,2,3,4,5,6,7,8,9,0).limit(4).forEach(System.out::println);

输出:

1
2
3
4

3.2.6、skip方法

如词义一样,这个方法用来跳过某个元素,如果说limit是截取后面的元素,那么skip就是截取前面的元素。

Stream.of(1,2,3,4,5,6,7,8,9,0).limit(4).skip(2).forEach(System.out::println);

输出:

3
4

3.2.7、flatMap方法

这个方法我的理解是,将流内存储的每个元素再转换为流,然后合并为一个流。

测试数据,下文都是使用此测试数据

ArrayList<Integer> arrayList1 = new ArrayList();
arrayList1.add(1);
arrayList1.add(2);
ArrayList<Integer> arrayList2 = new ArrayList();
arrayList2.add(3);
arrayList2.add(4);
ArrayList<Integer> arrayList3 = new ArrayList();
arrayList3.add(5);
arrayList3.add(6);

合并流

// 合并流
Stream.of(arrayList1,arrayList2,arrayList3)
  .flatMap(arrayList -> arrayList.stream()).forEach(System.out::println);

输出:

1
2
3
4
5
6

同时还可以对这个合并后的流进行一系列操作。

// 合并后把买个元素+1再输出
Stream.of(arrayList1,arrayList2,arrayList3)
  .flatMap(arrayList->arrayList.stream().map(value->value+1))
  .forEach(System.out::println);

输出:

2
3
4
5
6
7

3.2.8、peek方法

对Stream内的元素进行遍历处理,如果是引用类型,遍历的过程中可以对属性进行编辑,非引用类型的只能修改形参,不过可以在其lambda表达式内进行改变和测试。peek的操作是返回一个新的stream的,且设计的初衷是用来debug调试的,因此使用steam.peek()必须对流进行一次处理再产生一个新的stream

// peek可以对元素进行遍历,但是不能进行修改
Stream.of(arrayList1,arrayList2,arrayList3)
  .flatMap(arrayList -> arrayList.stream())
  .peek(v->{ v=v+1; }).forEach(System.out::println);

输出:

1
2
3
4
5
6

3.3、终端操作符

Stream流执行完终端操作之后,无法再执行其他动作,否则会报状态异常,提示该流已经被执行操作或者被关闭,想要再次执行操作必须重新创建Stream流

一个流有且只能有一个终端操作,当这个操作执行后,流就被关闭了,无法再被操作,因此一个流只能被遍历一次,若想在遍历需要通过源数据在生成流。

终端操作的执行,才会真正开始流的遍历。如 count、collect 等

3.3.1、collect方法

收集器,将流转换为其他形式,下面介绍两种比较常见的场景,它还有一些其他的功能,例如转换的时候可以做最大值、最小值、平均值、总和值、总数等操作。

转换为List:

List<Integer> collect = Stream.of(arrayList1, arrayList2, arrayList3)
  .flatMap(arrayList -> arrayList.stream()).peek(v -> {v = v + 1;})
  .collect(Collectors.toList());

转换为Map,转换时需要提供k,v的生成策略,都是根据Lambda表达式生成:

Map<String, Integer> collect = Stream.of(arrayList1, arrayList2, arrayList3)
.flatMap(arrayList -> arrayList.stream())
				.peek(v -> {
            v = v + 1;
        }).collect(Collectors.toMap(k -> "key" + k, v -> v));


        collect.forEach((k,v)->{
            System.out.println("key:"+k+",v:"+v);
        });

输出:

key:key1,v:1
key:key2,v:2
key:key5,v:5
key:key6,v:6
key:key3,v:3
key:key4,v:4

3.3.2、forEach方法

遍历流,这个方法上面已经演示很多次了就不再演示了,需要注意的是,如果是在中途需要遍历可以使用peek,因为forEach是终止操作符。

3.3.3、findFirst方法

返回第一个元素,默认返回Optional,可以使用get返回元素。Optional内内置了一些方法可以对存储的元素进行过滤,遍历等操作。

// 取出第一个元素
Optional<ArrayList<Integer>> first = Stream.of(arrayList1, arrayList2, arrayList3).findFirst();
// 取出元素
ArrayList<Integer> integers = first.get();

3.3.4、findAny方法

返回流中所有元素

// 取出所有元素
Optional<ArrayList<Integer>> first = Stream.of(arrayList1, arrayList2, arrayList3).findAny();
// 取出元素
ArrayList<Integer> integers = first.get();
System.out.println(integers);

返回:

[1, 2]

3.3.5、count方法

返回元素个数

// 取出所有元素
long count = Stream.of(arrayList1, arrayList2, arrayList3,null).filter(v->v!=null).count();
// 打印结果
System.out.println(count);

返回:

3

3.3.6、sum方法

求和,这个方法必须配合mapToInt、mapToLong等方法一起使用,下面介绍如何求集合内所有元素的和

// 取出所有元素
long count = Stream.of(arrayList1, arrayList2, arrayList3, null)
  .filter(v -> v != null)
  .mapToInt(v -> v.stream().mapToInt(item->item).sum()).sum();
// 打印结果
System.out.println(count);

返回:

21

3.3.7 、max方法

求最大值,需要指定根据什么比较,比如这个是根据长度比较,

// 指定比较的对象是什么
ArrayList<Integer> integers = Stream.of(arrayList1, arrayList2, arrayList3)
  .max(Comparator.comparingInt(value -> value.size())).get();

// 打印结果
System.out.println(integers.size());

输出:3

下面是先合并为一个大的集合,再根据元素内容比较

// 求最大值
        Integer max = Stream.of(arrayList1, arrayList2, arrayList3).flatMap(v -> v.stream()).max(Comparator.comparingInt(value -> value)).get();

        // 打印结果
        System.out.println(max);

输出:6

3.3.8、min方法

求最小值,用法与max相似,这里就不再演示了。

3.3.9、anyMatch方法

检查是否包含某个元素

// 是否符合个条件
boolean b = Stream.of(arrayList1, arrayList2, arrayList3).flatMap(v -> v.stream()).anyMatch(v -> v == 0);

// 打印结果
System.out.println(b);

输出:false

3.3.10、allMatch方法

检查所有元素是否都符合条件,与3.3.9方法类似,这里就不演示了。

3.3.11、noneMatch方法

检查是否有不满足条件的,与3.3.9类似,这里就不演示了

3.3.12、reduce方法

可以将流中元素反复结合起来,得到一个值,这里的reduce虽然只有两个参数,但是并非只会执行一次,而是会将参数依次代入执行。

// 结合
ArrayList<Integer> integers = Stream.of(arrayList1, arrayList2, arrayList3)
  .reduce((obj1, obj2) -> {
    obj1.addAll(obj2);
    return obj1;
  }).get();

// 打印结果
System.out.println(integers);

输出:

[1, 2, 3, 4, 5, 6]

3.4、Collect收集

Collector:结果收集策略的核心接口,具备将指定元素累加存放到结果容器中的能力;并在Collectors工具中提供了Collector接口的实现类

3.4.1、toList

将用户ID存放到List集合中

List<Integer> idList = userList.stream().map(User::getId).collect(Collectors.toList()) ;

3.4.2、toMap

将用户ID和Name以Key-Value形式存放到Map集合中

Map<Integer,String> userMap = userList.stream().collect(Collectors.toMap(User::getId,User::getName));

3.4.3、toSet

将用户所在城市存放到Set集合中

Set<String> citySet = userList.stream().map(User::getCity).collect(Collectors.toSet());

3.4.4、counting

符合条件的用户总数

long count = userList.stream().filter(user -> user.getId()>1).collect(Collectors.counting());

3.4.5、summingInt

对结果元素即用户ID求和

Integer sumInt = userList.stream().filter(user -> user.getId()>2).collect(Collectors.summingInt(User::getId)) ;

3.4.6、minBy

筛选元素中ID最小的用户

User maxId = userList.stream().collect(Collectors.minBy(Comparator.comparingInt(User::getId))).get() ;

3.4.7、joining

将用户所在城市,以指定分隔符链接成字符串;

String joinCity = userList.stream().map(User::getCity).collect(Collectors.joining("||"));

3.4.8、groupingBy

按条件分组,以城市对用户进行分组;

Map<String,List<User>> groupCity = userList.stream().collect(Collectors.groupingBy(User::getCity));

3.4.9、orElse(null)

    /**
     * Return the value if present, otherwise return {@code other}.
     *
     * @param other the value to be returned if there is no value present, may
     * be null
     * @return the value, if present, otherwise {@code other}
     * 返回值,如果存在,否则返回其他
     */
    public T orElse(T other) {
        return value != null ? value : other;
    }

表示如果一个都没找到返回null(orElse()中可以塞默认值。如果找不到就会返回orElse中设置的默认值)

3.4.10、orElseGet(null)

    /**
     * Return the value if present, otherwise invoke {@code other} and return
     * the result of that invocation.
     *
     * @param other a {@code Supplier} whose result is returned if no value
     * is present
     * @return the value if present otherwise the result of {@code other.get()}
     * @throws NullPointerException if value is not present and {@code other} is
     * null
     * 返回值如果存在,否则调用其他值并返回该调用的结果
     */
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();
    }

表示如果一个都没找到返回null(orElseGet()中可以塞默认值。如果找不到就会返回orElseGet中设置的默认值)

orElse() 接受类型T的 任何参数,而orElseGet()接受类型为Supplier的函数接口,该接口返回类型为T的对象

3.4.10、orElse(null)和orElseGet(null)区别:

1、当返回Optional的值是空值null时,无论orElse还是orElseGet都会执行

2、而当返回的Optional有值时,orElse会执行,而orElseGet不会执行

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class TestStream {

    public static void main(String[] args) {

        List<User> list = new ArrayList<>();

        //定义三个用户对象
        User user1 = new User();
        user1.setUserName("admin");
        user1.setAge(16);
        user1.setSex("男");
        User user2 = new User();
        user2.setUserName("root");
		    user2.setAge(20);
        user2.setSex("女");
        User user3 = new User();
        user3.setUserName("admin");
        user3.setAge(18);
        user3.setSex("男");
        User user4 = new User();
        user4.setUserName("admin11");
        user4.setAge(22);
        user4.setSex("女");
        //添加用户到集合中
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        /*
        在集合中查询用户名包含admin的集合
        */

        List<User> userList = list.stream().filter(user -> user.getUserName().contains("admin")&& user.getAge() <= 20).collect(Collectors.toList());
        System.out.println(userList);

        /*
        在集合中查询出第一个用户名为admin的用户
        */

        Optional<User> user = list.stream().filter(userTemp -> "admin".equals(userTemp.getUserName())).findFirst();

        System.out.println(user);

        /*
        orElse(null)表示如果一个都没找到返回null(orElse()中可以塞默认值。如果找不到就会返回orElse中设置的默认值)
        orElseGet(null)表示如果一个都没找到返回null(orElseGet()中可以塞默认值。如果找不到就会返回orElseGet中设置的默认值)
        orElse()和orElseGet()区别:在使用方法时,即使没有值 也会执行 orElse 内的方法, 而 orElseGet则不会
        */
        //没值
        User a =  list.stream().filter(userT-> userT.getAge() == 12).findFirst().orElse(getMethod("a"));
        User b =  list.stream().filter(userT11-> userT11.getAge() == 12).findFirst().orElseGet(()->getMethod("b"));

        //有值
        User c =  list.stream().filter(userT2-> userT2.getAge() == 16).findFirst().orElse(getMethod("c"));
        User d =  list.stream().filter(userT22-> userT22.getAge() == 16).findFirst().orElseGet(()->getMethod("d"));


        System.out.println("a:"+a);
        System.out.println("b:"+b);
        System.out.println("c:"+c);
        System.out.println("d:"+d);
    }

    public static User getMethod(String name){

        System.out.println(name + "执行了方法");
        return null;
    }
}

4、Optional

5、新的日期格式

6、其他特性

参考:Java--Stream流详解,后面相当一部分是直接粘贴的,基本等于转载了~,大家可以看看原文哦

标签:JDK1.8,stream,Stream,System,特性,50,println,out
From: https://www.cnblogs.com/zhangruifeng/p/17134034.html

相关文章

  • ESD静电保护二极管 SD36C特性和参数介绍
    静电保护器件对于电子工程师而言,并不陌生,在各类通讯接口端口总能看到它的身影,比如RS-485端口专用静电二极管SM712、CAN总线选用NUP2105L、HDMI高清端口选用RCLAMP0524P。静......
  • 正式抛弃 Feign!Spring 6 推出新特性:HTTP Interface,这波太秀了!
    来源:https://juejin.cn/post/7173271507047546893近期,Spring6的第一个GA版本发布了,其中带来了一个新的特性——HTTPInterface。这个新特性,可以让开发者将HTTP服务......
  • 16.Rust的面向对象编程特性
    面向对象编程(Object-OrientedPrograming,OOP)是一种程序建模的方法。一、面向对象语言的特性编程社区对面向对象语言的特性没有一个共识性的结论。但是对Rust来说,面向对......
  • linux系统安装jdk1.8、mysql5.7、redis(压缩包版本教程)
    linux系统安装jdk1.8、mysql5.7、redis(压缩包版本教程)在内网环境中的linux系统上安装环境,十分的麻烦(没有网络)一、安装jdk1.81.在use/local下创建相关文件夹:1.mkdirja......
  • Sql Server 加速数据库恢复特性(此部分介绍来源于微软官方文档)
                加速数据库恢复是sqlserver于2019版本开始引入的一项新特性,简称ADR。           ADR的主要优势在于:快速且一致的数据库恢复......
  • 读Java实战(第二版)笔记11_语言特性和类库更新
    1. 注解1.1. 一种使用附加信息装饰程序元素的机制1.2. Java8之前,只有声明可以被注解1.3. 一种语法元数据(syntacticmetadata)1.4. 可以用于文档编制1.4.1. @De......
  • 一封传话聚合推送高级特性API
    一封传话聚合推送高级特性API前言上一次介绍了一封传话的API文档的主要推送API,主要用于实现快速推送到微信、企业微信、钉钉、飞书、邮箱、自定义Webhook。集成该API后仅......
  • Java 8新特性之 Optional 类
    前言java.util.Optional是java8中引进的一个新的类,我们通过Optional类的源码可以看到,该方法的作用可以对可能缺失的值进行建模,而不是直接将null赋值给变量。Optional类......
  • JavaScript对象属性的特性高级功能
    “usestrict”/创建一个对象最简单的方式:创建一个Object的实例,然后再为它添加属性和方法/varperson=newObject();person.name=“Hongbin”;person.age=21;per......
  • 这些JDK8 新特性,我还是第一次听说
    文章内容整理自博学谷狂野架构师概述什么是函数式接口?简单来说就是只有一个抽象函数的接口。为了使得函数式接口的定义更加规范,java8提供了@FunctionalInterface注......