首页 > 编程语言 >Java8新特性

Java8新特性

时间:2022-09-18 20:22:53浏览次数:84  
标签:stream author System 特性 authors println Java8 out

1. lambda表达式

即允许将函数作为参数传递进方法中。可以替代匿名内部类的编写
新手一开始不能直接写出lambda表达式,我们可以先用Idea的提示写出匿名内部类,匿名内部类比较好看懂,写好之后再用Idea的提示将匿名内部类转为lambda表达式,熟练之后我们就可以独立写出lambda表达式了。

2. Stream流

最后必须有终结方法的调用,否则中间方法都不会执行

因为Stream流是惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行

可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。

先创建好author集合方便后边使用

private static List<Author> getAuthor(){
    //数据初始化
    Author author = new Author(1L,"程长新",33,"一个从菜刀中明悟哲理的祖安人",null);
    Author author2 = new Author(2L,"李丽云",16,"狂风也追逐不上他的思考速度",null);
    Author author5 = new Author(2L,"程杨",15,"狂风也追逐不上他的思考速度",null);
    Author author3 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
    Author author4 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);
    //书籍列表
    List<Book> books1 = new ArrayList<>();
    List<Book> books2 = new ArrayList<>();
    List<Book> books3 = new ArrayList<>();
    books1.add(new Book(1L,"刀的两侧是光明与黑暗","哲学,爱情",88,"用一把刀划分了爱恨"));
    books1.add(new Book(2L,"一个人不能死在同一把刀下","个人成长,爱情",88,"用一把刀划分了爱恨"));

    books2.add(new Book(3L,"那风吹不到的地方","哲学",88,"带你用思维去领略世界的尽头"));
    books2.add(new Book(3L,"那风吹不到的地方","哲学",88,"带你用思维去领略世界的尽头"));
    books2.add(new Book(4L,"吹或不吹","爱情,个人传记",88,"一个哲学家的恋爱观注定很难把他"));

    books3.add(new Book(5L,"你的剑就是我的剑","爱情",88,"无法想象一个武者能对他的伴侣这么"));
    books3.add(new Book(6L,"风与剑","个人传记",88,"两个哲学家灵魂和肉体的碰撞会激起这么"));
    books3.add(new Book(6L,"风与剑","个人传记",88,"两个哲学家灵魂和肉体的碰撞会激起这么"));

    author.setBooks(books1);
    author2.setBooks(books2);
    author3.setBooks(books3);
    author4.setBooks(books3);
    author5.setBooks(books1);

    List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4,author5));
    return authorList;
    }

1. 创建流

1.1 单列集合创建流

直接集合对象.stream()就可以返回Stream对象了

比如List对象

List<Author> authorList = getAuthor();
Stream<Author> stream = authorList.stream();
1.2 数组创建流

Arrays.stream(数组)

int[] arr = {1,2,3,4,5};
IntStream stream = Arrays.stream(arr);
stream
    .filter(number >3)
    .forEach(number ->System.out.print(number));
//结果输出是4	5
1.3 双列集合创建流

Map即双列集合,需要转换为单列集合才可以创建流

Map<String, Integer> map = new HashMap<>();
map.put("程长新",12);
map.put("李丽云",14);
map.put("程杨",16);
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Stream<Map.Entry<String, Integer>> stream = entrySet.stream();
stream
    .filter(entry -> entry.getValue()<15)
    .forEach(entry -> System.out.println(entry.getKey()+"---"+entry.getValue()));
//结果输出是程长新---12		李丽去---14

2. 常用中间操作

2.1 filter(变量 -> 判断条件)

过滤,返回boolean,判断每一条流数据是否符合条件,如果返回false则去掉该条数据。

即过滤掉流中不符合条件的数据

2.2 forEach(变量 -> 操作)

遍历流中的每一条数据,进行操作

2.3 map(变量 -> 操作)与flatMap()

都可以对流中的数据进行计算或转换

map只能将流中的一条对象转换为另一个对象来作为流中的元素,而flatMap可以将一个对象转换为多个对象再作为流中的元素(因为flatMap操作的返回结果也是stream,即可以将一个对象转换为流后返回)

为了减少后期对基本数据类型操作的自动拆装箱时间,JDK也提供了直接将数据转化的基本数据类型的map方法mapToInt()、mapToLang()、maoToDouble()以及对应的flatMap的方法

//将名字长度大于7的都转为大写输出
List<String> list = Arrays.asList("ChengChangxin", "LiLiyun","ChengYang");
list.stream()
    .filter(name -> name.length()>7)
    .map(name -> name.toUpperCase())//对流中的数据进行操作后返回
    .forEach(name -> System.out.println(name));
//flatMap()
//将每个作者的书都打印出来并去重
List<Author> authors = getAuthor();
authors.stream()
    .flatMap(author -> author.getBooks().stream())
    .distinct()
    .forEach(book -> System.out.println(book.getName()));

//加深flatMap理解,将所有书的所属分类打印出来,一个一个打
//打印所有分类并去重,一个一个打,不能出现逗号
System.out.println("所有分类============");
authors.stream()
    .flatMap(author -> author.getBooks().stream())//先拿到每个作者的所有书
    .distinct()//对书去重
    .flatMap(book -> Arrays.stream(book.getCategory().split(",")))//拿到分类后按逗号分隔为数组再转为stream返回
    .distinct()//对分类去重
    .forEach(category -> System.out.println(category));
2.4 distinct()

对流中的数据去重

distinct依赖的是object的equals方法来判断是否是相同对象的

所以如果需要的话要重写equals方法,因为equal方法只有在对象地址相同时才是相同对象,如果我们想对象值相同即为相同对象的话就要重写equal方法

2.5 sorted()

sorted()有两个重载方法

  • 一是无参的方法

    无参方法需要流对象自己已经实现Comparable接口,定义好比较规则

  • 二是有参的方法

    传递Comparable匿名内部类自己定义比较规则

List<String> list = Arrays.asList("ChengChangxin", "LiLiyun","ChengYang");
list.stream()
    .sorted()//list对象已经实现了comparable接口,所以可以直接调用无参的sorted方法
    .forEach(name -> System.out.println(name));
List<Author> authors = getAuthor();
authors.stream()
    .sorted()//手动为Author类实现comparable接口
    .forEach(author -> System.out.println(author.getName()+"---"+author.getAge()));
//结果
ChengChangxin
ChengYang
LiLiyun
程长新---33
李丽云---15
易---14
易---14

为Author类实现comparable接口

image-20220916223039290

调用有参的sorted方法

List<Author> authors = getAuthor();
authors.stream()
    //                .sorted()//手动为Author类实现comparable接口
    /*.sorted(new Comparator<Author>() {
                    @Override
                    public int compare(Author o1, Author o2) {
                        return o1.getAge() - o2.getAge();
                    }
                })*/
    .sorted((o1,o2) -> o2.getAge() - o1.getAge())
    .forEach(author -> System.out.println(author.getName()+"---"+author.getAge()));
//结果
程长新---33
李丽云---16
程杨---15
易---14
易---14
2.6 limit(n)方法

限制stream流中的数据条数,只留下前n条

比如要输出年龄最大的前两个作家。思路是对作家排序后只留下两个

//limit()方法
System.out.println("年龄最大的前两位");
authors.stream()
    .sorted((o1,o2) -> o2.getAge() - o1.getAge())
    .limit(2)
    .forEach(author -> System.out.println(author.getName()+"---"+author.getAge()));
//结果
年龄最大的前两位
程长新---33
李丽云---16
2.7 skip(n)方法

跳过流中的前n条数据,只留下后边的数据

//需求:打印除了年龄最大的其余所有人
List<Author> author = getAuthor();
author.stream()
    .distinct()
    .sorted()//按年龄降序排
    .skip(1)//跳过第一个年龄最大的
    .forEach(one -> System.out.println(one.getAge()+"---"+one.getName()));
//author中原来数据
	33---程长新
    16---李丽云
    15---程杨
    14---易
//使用skip(1)后的
    16---李丽云
    15---程杨
    14---易

3 常用终结操作

3.1 forEach()

对流中的每个元素进行遍历

3.2 count()

统计流中的元素个数,是long类型的返回值

3.3 max()和min()方法

对流中的元素求最大和最小值,返回optional对象

//获取评分最高的书籍
List<Author> authors = getAuthor();
Optional<Integer> max = authors.stream()
    .flatMap(author -> author.getBooks().stream())
    .map(book -> book.getScore())
    .max(new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2;
        }
    });
System.out.println(max.get());
3.4 collect()方法

将流数据收集为集合对象。在collect()中传递Collectors工具类的方法即可

//获取一个存放作者名字的list集合
List<Author> authors = getAuthor();
List<String> nameList = authors.stream()
    .map(author -> author.getName())
    .collect(Collectors.toList());
System.out.println(nameList);
//获取所有书名的set集合
Set<String> bookSet = authors.stream()
    .flatMap(author -> author.getBooks().stream())
    .map(book -> book.getName())
    .collect(Collectors.toSet());
System.out.println(bookSet);
//获取map,键为作者名字,值为book集合
Map<String, List<Book>> authorMap = authors.stream()
    .distinct()//因为map键不能重复,所以要对作者去重
    .collect(Collectors.toMap(/*map的键*/author -> author.getName(), /*map的值*/author -> author.getBooks()));
System.out.println(authorMap);
3.5 查找和匹配方法
(1)anyMatch()

流中的数据有一条符合条件就返回true,全都不符合则返回false

List<Author> authors = getAuthor();
//看所有作者中是不是有大于20岁的
boolean b = authors.stream()
    .anyMatch(new Predicate<Author>() {
        @Override
        public boolean test(Author author) {
            return author.getAge() > 20;
        }
    });
System.out.println("看所有作者中是不是有大于20岁的: "+b);
(2)allMatch()

流中的所有元素符合条件才返回true

(3)noneMatch()

流中的所有元素都符合条件才返回true

//看是不是所有作者都不到60岁
List<Author> authors = getAuthor();
boolean b = authors.stream().noneMatch(author -> author.getAge() > 60);
System.out.println("看是不是所有作者都不到60岁: "+b);
(4)findAny()

随便取流中的一条数据

(5)findFirst()

取流中的第一条数据

(6)reduce()归并方法

对流中所有元素进行指定操作之后返回一个值

  • 重载方法一

    reduce(参数一,参数二)

    参数一为初始值 ,它的类型为当前流中数据中类型,参数二为指定操作,最后返回结果类型也是流中数据类型

  • 重载方法二

    reduce(参数)

    不用指定初始值 ,处理过程中会把流中第一条数据作为初始值 ,只指定操作就可以,返回值为optional类型

List<Author> authors = getAuthor();
Integer reduce = authors.stream()
    .map(author -> author.getAge())
    .reduce(0, (result, age) -> result + age);//第一个参数(0)是初始值,第二个参数((result,age))中的第一个是结果变量,第二个是流中的每一个元素
System.out.println("作家年龄和:"+reduce);

//最大年龄作家
Integer maxAge = authors.stream()
    .map(author -> author.getAge())
    .reduce(Integer.MIN_VALUE, new BinaryOperator<Integer>() {
        @Override
        public Integer apply(Integer result, Integer age) {
            return result < age ? age : result;
        }
    });
System.out.println("用reduce找出年龄最大的作家:"+maxAge);

//最小年龄作家
Integer minAge = authors.stream()
    .map(author -> author.getAge())
    .reduce(Integer.MAX_VALUE, (result, age) -> result < age ? result : age);
System.out.println("用reduce找出年龄最小的作家:"+minAge);

//用一个参数的重载方法进行计算最大年龄
Optional<Integer> max = authors.stream()
    .map(author -> author.getAge())
    .reduce((result, age) -> result > age ? result : age);
System.out.print("用一个参数的重载方法进行计算最大年龄:");
max.ifPresent(age -> System.out.println(age));

4 并行流

将流数据放到多个线程中进行处理,对处理大批量数据时是友好的。

对象直接调用parallelStream()方法就可以返回并行流数据

或者调用stream()获取到流数据再调用parallel()方法将串行流转换为并行流

peek()方法是专门用来测试流数据的方法

List<Author> authors = getAuthor();
authors.parallelStream()
    .peek(author -> System.out.println(author.getName()+"==="+Thread.currentThread().getName()))
    .forEach(author -> System.out.println());
boolean parallel = authors.stream()
    .parallel()
    .isParallel();
System.out.println(parallel);
//结果,可以看到流数据在多个线程中运行
易===main
程杨===ForkJoinPool.commonPool-worker-2
李丽云===ForkJoinPool.commonPool-worker-1
易===ForkJoinPool.commonPool-worker-1
程长新===ForkJoinPool.commonPool-worker-3
true

3.Optional对象

目的是为了避免空指针异常的出现

1 Optional对象的创建

使用Optional类的静态方法ofNUllable(对象)即可将对象包装为Optional对象

如果确定对象不为空的话可以直接使用of(对象)来包装对象,当出现空的时候用empty()来替代则可以不报错

所以一般都使用ofNullable(对象)来创建Optional对象,不用关心对象是否为空

private static void optionalCreateTest() {
    List<Author> authors = getAuthor();
    //用Optional的静态方法ofNullable来包装对象,可以接受空值
    Optional<List<Author>> authorsOptional = Optional.ofNullable(null);
    Optional<List<Author>> authorsOptional1 = Optional.ofNullable(authors);
    //当确定对象不是空值的时候可以用of()直接来包装,但传入null时会报空指针异常
    Optional<List<Author>> authorsOptional2 = Optional.of(authors);
    //        Optional<List<Author>> authorsOptional3 = Optional.of(null);//会报错
    //如果确实需要封装空对象,可以使用empty()方法
    getAuthorOptional();
}

private static Optional<Author> getAuthorOptional() {
    //        Author author = new Author(1L,"小小",33,"一个从菜刀中明悟哲理的祖安人",null);
    Author author = null;
    return author == null ? Optional.empty() : Optional.of(author);
}

2 安全的消费值

调用Optional对象的ifPresent()方法

即对象中有内容时才执行传递的操作

Optional<Author> authorOptional = getAuthorOptional();
authorOptional.ifPresent(author -> System.out.println("作家姓名:"+author.getName()));

3 安全的获取值

如果直接用get()来获取的话当对象中为null的时候会报错

可以用orElseGet()方法。如果authorOptional中有值就话返回它的值,如果它是空就返回后边的默认值

Optional<Author> authorOptional = getAuthorOptional();
Author author = authorOptional.orElseGet(() -> new Author(1L,"长新",3,"一个从菜刀中明悟哲理的祖安人",null));
System.out.println(author.getName());

也可以用orElse(直接指定默认值),这个方法不用传lambda表达式,直接把默认值作为参数

当值为null时抛出自定义异常orElseThrow()

Optional<Author> authorOptional = getAuthorOptional();
try {
    Author result = authorOptional.orElseThrow(() -> new RuntimeException("自定义异常:数据为null"));
} catch (Throwable e) {
    e.printStackTrace();
}
//当authorOptional为空时抛出如下异常
//java.lang.RuntimeException: 自定义异常:数据为null

4 过滤filter()

与stream的使用一样

5 判断1isPresent()

判断Optional对象中是否有值,返回boolean

6 map()方法

与Stream的map()方法一样

标签:stream,author,System,特性,authors,println,Java8,out
From: https://www.cnblogs.com/ccx-lly/p/16705648.html

相关文章

  • Java8/18
    Java流程控制1.用户交互ScannerScanner是Java5提供的一个工具类(java.until.Scanner),用来获取用户的输入,实现人机交互。基本语法:Scanners=newScanner(System.in);......
  • Java8/18
    Java方法1.方法概念eg:System.out.println();----System是一个系统类,out是System类的一个输出对象,println()就是一个方法什么是方法:Java方法是语句的集合,他们在一起执行......
  • 【Mysql】事务的基本特性和隔离级别
    事务的基本特性ACID分别是:原子性(atomicity)指的是一个事务中的操作要么都成功,要么都失败。一致性(consistency)指的是数据库总是从一个一致性状态转移到另外一个一致性状态。......
  • JAVA8 - 流
    packagecom.day01;importorg.junit.Test;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.List;importjava.util.stream.Stream;/***......
  • 【java8新特性】01:函数式编程及Lambda入门
    我们首先需要先了解什么是函数式编程、函数式编程是一种结构化编程范式、类似于数学函数、它关注的重点在于数据操作、或者说它所提倡的思想是做什么,而不是如何去做。自J......
  • 【转载】数据库事务的四大特性
    数据库事务的四大特性(ACID)ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持......
  • 11.5面向对象的三大特性
    #面向对象三大特性:封装继承多态#广义得封装:#把方法和变量都封装在类中#比如人狗大战#规范创建对象#创建所有人得属性名都能一致#......
  • java8新特性:方法引用
    java8新特性:方法引用我们用Lambda表达式来实现匿名方法。但有些情况下,我们用Lambda表达式仅仅是调用一些已经存在的方法,除了调用动作外,没有其他任何多余的动作,在这种情况......
  • Java8Stream流复习和api总结
    构建方式list.stream();Stream.of(list);基础常用APIStream<Number>stream=list.stream();//获取最大值stream.max(比较器);//获取最小值stream.min(比较器);......
  • vue3 基础-non-props 特性
    本篇探讨当父组件通过属性给子组件传数据时,子组件如果不通过props属性进行接收,那数据会挂载到哪里,以及子组件如何能使用这些数据.正常的父子组件传值<!DOCTYPEh......