three utils 生成一切对象树形结构?大家好,今天跟大家分享一个在骄傲层面的通用的生成树的一个工具类,就是吹 utils 树结构在日常的开发中也是多多少少都遇见,比如就像资源树啊、分类树啊, 或者菜单数啊,部门数啊,这些都会遇到,都需要生成树形的结构。然后就比如这边的资源,资源资源树,他就是一个树形结构, 比如你下运维下面有项目管理,项目管理下有这些的权限,这就是一个典型的塑形结构。我们可以看一下请求的接口的话,他就其实也是一个塑形结构。 返回的接口呢,就是比如你这边的运维,运维下面有一个指一些指节点,指节点就是有项目管理机械 列表,项目管理下又有一些指节点,就是一些权限的节点,这就是一个典型的数。 好,我们来看一下他大致实线吧,通过去 uts 这个工具类来实现生成数,我们来先看一下他接口,比如就像这个是就这个,这个就是后端的接口,掉一下的话,他其实就是生成一棵树,返回来了就已经是一棵树又去了,这这里面有这些,这边有个指指节点, 把它对应过来的归对应过来的方法其实就是在这个这个 ctrl 里面的,这个方法好掉了,其实就是先获取到出出去,从数据库里面查出所有的 所有的节点资源节点,然后再把它通过 tutors 直接去生成他的一个树,一颗一颗一些一个树形结构的列表,大致就是这样。那我们可以先来点 bug 一下, 然后你看,其实可以你看进进来的话,通过这边计算的话, 他他就是返回所有数据库里面所有的一些资源嘛。比如他现在还不是一棵树,不是一棵棵树就是所有的资源列表 啊,经过去 uts 生成之后,生成树之后他就会变成一颗一颗的树结构,你看总共就相当相当于有四棵树, 就是首页啊、运回啊这些的点进来的话,他就有指节点,又有两个 好,这边又有指节点十四个,相当于是这样就可以生成这通用的数,然后然后去 uts 就是 他,可不,他不止他可以生成所有的对象的一棵树不一定只有资源数,比如像我这边他还有其他地方也有生成这个数,比如像账号的权限的时候,也需要根据账号 id 获取所有他的他的资源数,也是用这个通用的方法去生成, 就避免没因为就避免每个每棵树都要去写写一些重复的地规啊,这就去生成树,比如有分类树或者部门树或者菜单树, 那我还要难道还要写三个三个类型的不同的地规去去生成数吗?那就比较麻烦了啊。今天主要就是分享一个这个吹油铁石来统一生成数,我们现在去参观看一下他的大致实现。 大致实现就是其实一棵树树结点的话,它都有一些通用的一些属性,比如我们就首先需要定一个 树节点的一个接口树,一棵树一棵树上面的节点肯定就有他这个节点上的标识吗?以及他的副副标识,还有因为因为因为你这些标识的话可能是比如乱类型或者是菌类型都有可能,所以说就相当于给他了一个放心 就可以更通用一点,比如你可以支持 steam 或者乱类型或者 intage 类型都可以。那还有一棵树就是比如需要判断这棵这个树节点是是不是根节点,有的有的系统可能是以 呃零为代表负节点,也有可能以空值为代表负节点,都有可能,所以说就相当于给他一个抽象,就是给他一个方法让他实现是不是负节点。 还有一些就是通用的嘛,速度一些指节点,设置他的指节点这些,然后我们就可以看一下,比如上面的就实现了, 就是说是历史 vo 已经实现了,它就相当于去实现这个这个节点,然后就要去实现它这些方法。我们的标识就是它的 id 嘛啊,副标识就是它的 p id 嘛, 对应的是 p i d, 然后节点的话,我这边的话是以零代表为根节点,就是相当于是如果你返回的这个 p i d 是等于零,它就是代表这这个这个节点是一个根节点,然后面就是设置它的一个指节点,主要就是这些方法,然后 然后实现完了这个接口之后就可以通,就可以用他的这个通用方法,就是生成数数列表, 就就就就像上面的调用的方法一样,就 return tree, 就是直接这样子,可以直接就生成一个数。它的实现的话其实就是先获取所有的跟结点,然后用 迭代器去迭代它,如果如果是如果调用它的路程方法是根节点,就相当于把它添加到这个根所有根的列表里面, 然后再把再把这个这个节点删除掉,就避免在后面,后面,后面你设置节节,指节点的时候还需要去便利这这些节点吗?所以说就避免后后续去重复便利这个节点,就相当于把它删掉,后面就是接下来就是去便利根节点,然后设置这个根节点的指节点。 指节点的话,其实也就是就是这个是根节点嘛,就相当于是副节点,而这下这就是剩下的一些节点,然后通过去也是通过叠带去去便利。然后如果根节点的副节点等于这个节点的话, 就相当于是他的子就是他的孩子嘛,就相当于给他添加进去,如果这个孩子不为空的话,就相当于是设置, 就相当于是设置到调用他的这个接口的直线类,把他把这个指孩子是设设置到这个负节点里面,就相当于这样子就就实现了设置他的指节点,后面就是重重重复的地规嘛,然后指节点,再设置指节点,就是相当于这边就是地规设置指节点。 当然还有一些,比如,比如可以获取到他所有的列子节点嘛,比如也可以,这是这个也是一个通用的方法,就是获取到这个这个树,这些树的所有的叶子节点嘛, 好,通过这样的方法就省的,比如你,你比如你有分类数或者什么或者菜单数、资源数,就可以直接通用一个方法直接去实现每个每他的对象去实现这个这个接口就好了,就避免你, 比如,比如分类数再递规一次,菜单数再递规一次,然后什么部门数又去递规,重复递规一次?因为代码都是类似的,只是他的实力对象不一样而已,所以说我们就可以通过抽象的方法来给他实现。 那今天的分享大致就是这样。嗯,感谢大家的观看。
粉丝88获赞409

你知道创建一个对象有多复杂吗?这个视频以扎瓦为例,浅显的解释一下 g v m 当中扎瓦对象是如何被创建的。我们以这段代码为例子,一个再普通不过的 person lay, 包含 name 和 age 两个字段。在 me 中我们创建一个 person 类的实力,然后把这个实力的 name 打印出来。编一转的代码会生成一个 class 文件,我们用扎瓦 p 工具可以把 class 文件当中的字解码打印出来。可以看到在字解码中,关于对象创建,第一条也是最重要的一条指令就 new。 后面这景七是对类型的引用输出,也展示了指向的就是代码里写的 person 类型,自己码的任务到这就算完成了。具体怎么 new 这个对象呢? 这就是 j v m 需要解决的问题了,这就是 j d k 十七的原代码,里面包含了 hot spot 这个应用最为广泛的扎瓦虚拟机实现 hot spot 代码量巨大。为了让大家更好的理解创建对象的过程,我们先不看具体的 代码,而是了解一下从高层角度看 hotspot 中扎瓦对象是如何存在的。我们知道在扎瓦中,除了基础类型之外的对象都继承自扎瓦点浪点 of jackt, 但这仅仅是停留在扎瓦层面。 hotspot 是使用 c 加加实现的,它需要用某种方式来实现扎瓦对象的各种功能。 hotspot 的方式被称为 op class 模型, 听起来挺复杂的对吧?其实仔细说呢,确实非常非常复杂。本视频还是本着抛砖引玉的精神,试图结合着代码给大家简单讲一下这个东西。首先 class 和 op 是两个 c 加加类,一个 class 对应一个 java 类,而一个 oop 对应一个 java 对象。回到最开始的代码例子, 在扎法层面有一个 person 类,意味着 c 加加层面就有一个 class 实力对应 person 类。而我们创建的 a 这个对象在 c 加加层面就是一个 o o p 实力。为什么要拆成两个东西呢?在 houseboard 源码里有解释, class 头文件里的注释是这样说的, 分开 o o p 杠 class 的一个原因是我们不想让每个对象里都有 c 加 v table 指针。正常的 o o p 对象里没有任何虚方法,他们将所有的虚方法转发给对应的 class, 而 class 中包含 v table, 并且可以根据实际类型进行 c 加加的动态调用。 学过 cr 家的同学应该能理解了,续函数表对于内存来说是比较大的负担, o o p 没有续函数表会极大的节省内存使用。由于拆分了全责, o o p 的实现相当简单, 这就是 op 的实现类,名字叫做 op desk, 它里面就俩字段,一个是 mark word, 另一个是 matadata。 这俩东西就是很多文当中都会提到的扎把对象头,其中 matadata 里有一个指向克拉斯的指针,对象跟类就这么被联系起来了。聪明的同学可能已经想到一个问题了,对象也不能只有头啊, 比方我们的 person 里面有内幕,有 age, 这些东西存在哪呢?答案是直接往 o o p desk 的后面存,这就是 hot sport 里对 c 加加的 利用和扩展了。我们假设这是 percent a 的内存,表示前面的 mark word 和 mate data 就是正常的 op desk 里面的对向头,紧接着后面就是一个 int, 也就是 age, 然后就是一个 string 引用,也就是内幕。顺序的话可能跟代码定义的不完全相同, 大家不用在意。再往后后面可能还会有判定填充整个包含对象头的这一大块东西才是一个完整的扎瓦对象的内存表示。为了方便获取后面的各种字段, op desk 里提供了 feel the dress, object feel the dress 等方法。他们的实现就是拿当前对象的指针,然后往后面加 offset 算 口述物品。我们可以实际看一下真实运行的扎瓦程序中内存的样子,我们使用 j h s d b 就可以查看扎瓦程序的内存详情。先从 stack memory 里找到 person 对象的位置,第一个地址是 stack memory 的值,第二个地址就是对象存储的值。把第二个地址填到 memory viewer 里,前面这三行就是 person 对象, 第一行是 macword, 第二行的后半部分是 mate data 指针,第二行的前半部分是十六,进制的十八,也就是我们填的 age 十八。第三行是对 string 的一个引用, 也就是内蒙。说了这么多,应该算是把渣的对象在内存中的表示给说清楚了。有了这些基础知识之后,再去理解 j v m 元代码就会简单很多。下面我们看一下 hot sport 中 bitcoin interpreter 中 new 这个指令的实现。 bitcoin tupper 是一个解释型的实现,并不是实际上跑的实现,不过用来理解 v m 工作过程是没问题的。 深入理解扎法训练机中也是用它做的例子,这就是 new 的实现。首先可以看到它的主逻辑是先判断用不用 tlab, 也就是县城本地存储,如果使用县城本地存储的话,就不用去全局堆上见对象了,也就不需要县城间的同步了。 首先他拿到了一个 class 实现,也就是要先拿到类的有关信息,然后 cast 成了 instance class 这个 class 的子类。再往后他算了一下整个对象的大 角,然后去 tlab 里分配了对应的大小,得到了 result 这个内存指针,然后把 result 这个指针 cast 成 op desk 星儿类型,设置上默认的 mark word 以及 matareta 信息,这个对象在 hotspot 层面就已经创建完成了。回到最开始的反面一解舞,我们会看到后面其实还有一个重要指令,就是 emok special, 用来调用对象的银 neat, 也就是扎瓦里的 constructor, constructor 里面就是扎瓦程序员可以控制的了。完成这一步之后,整个扎瓦对象才算是在扎瓦层面可用了。好了,今天的视频到这就结束了,希望能让大家对扎瓦对象有更深刻的认识吧。

今天给大家介绍一个非常简单的一个小功能,但是在我们日常携带码的时候,是一个非常常用的一个功能啊,就是我们去扭一个对象的时候,比如我们扭一个 every list, ok, 这就是我们一个日常的写法。那么如果配合爱迪尔的快捷键,我们应该怎么样去操作呢? 主要分为三步就可以完成一个家有对象的床垫, 看我操作,这时候点尿回收, ctrl 加奥特加微 选择你的面料,结束了,你学会了吗?


好,那上节呢,我们就把这个创建对象哎给你看了啊,就是如何去实力化这个对象,这个呢我们就已经看完,看完之后我们接下来呢来再去给你定一个类,来,去把这个创建对象呢,再去给你加长一下啊,好,我们就开始去在这个地方呢来去创建一个类,那么 这个类我们的一个需求是什么呢?哎,要创建的这个类是什么类呢?来我们创建一个道个,这个类就是创建狗这个类, 那你想去创建这个道个类啊?你是来去描述啊?我们说一上来是不是做一个抽象,做一个描述的一个过程啊?对吧?好,来去描述这个道个他的一个状态行为啊,对吧?就是他的一个状态和行为啊。好,来去怎么样去描述啊?好,来去描述这个,那么 首先是不是他这个状态状态呢?哎?是不是道个他里边应该是有哪些信息啊?这个信息呢?由你自己来去定,你想让他有哪些信息, 把这些信息呢给他写到这里就行了。好,就比如啊,我在这里边呢,我来去给他写上啊,这个道哥呢?他有这个名字,然后呢这个道哥呢?他有这个年龄,然后呢 这个道个呢?然后他有这个颜色的吧?好,里面呢有这个颜色,然后道个呢?他有这个品种的吧?好,来写上一个太婆。 ok, 这是我们给这个道个来去定义的一些状态。明白 这个状态抽象的一个过程是你自己来去定义的,你可以去决定他里面有哪些这个状态。好,那么状态有了之后呢?然后底下呢是他的一个行为。好,那么行为里边呢我们就写上一个 party, 一个行为是不是用方法来去表示啊,对吧?好,帕布雷克一个 word 的 word 冲呢里面做一个 e t 让他来去吃。好, 他吃什么呢?由你来去决定。哎,你可以去给他传递个参数啊,来传递个这个副的给他。好,那么这个吃的时候呢?哎,他吃之前呢先去介绍 他自己,哎,他名字叫什么呀?在这个地方呢,哎,就是这个名字啊名字呢?哎,写上这个字符好,名字,哎,叫什么?什么耐木啊,对吧?好,然后再再去加上他的一个品种来在这里边呢写上一个品种。好,那么,哎,这个品种是这样的哈品种,然后加上是不是他这个太太啊,对吧? 好,然后呢再去加上这个颜色,好,里面呢再去写上这个颜色来写到这里啊写上个颜色,然后呢你等于等于写了加上你的这个咖了,那年龄呢我们就不要了 这个爱转呢我就不要了哈,把它去掉,那么年龄呢,你也可以去使用死菌类型的来去表示,哎,你使用什么类型来去表示?你到时候写的时候你就必须给他什么类型。明白。好,那你如果说年龄呢写的是死菌类型,到时候你给他是不是必须是这种形式啊,对吧?好,那这一式关于我们的这一块我们不要这个年龄了啊,哎,我们呢就看 定义这个内蒙你的一个卡了,你这个太婆,对吧?好,那么你吃之前呢,你先去把这个给我介绍一下啊。好,介绍完了之后呢,然后,哎在底下这个位置呢再去输出一句话输出水来输出,哎这个名称,哎,这个耐磨啊,耐磨,加上来写上一个吃吃之后呢,加上我们那个副的 来,那么这个呢,我们就给他写好,就是写了一个道格这个类,对吧?而且一个道格这个类之后呢,哎,里边有个行为,就让他吃的这个行为,他吃什么呢?由你来决定。好,他吃的时候呢,你必须让他来介绍一下名字叫什么品种什么样子的,颜色是什么样子的,来, 你是不是来去介绍一下,对吧?好,那么哎,在这里边呢,来,直接是给你写好,写好之后我们就可以去根据这个道格类来去创建具体的这个对象了。好,好,那同样呢,在底下这个位置呢,我们再去定一个这个太死的类啊, 就要你在这里边定义的这个泰斯莱里,就不能叫这个泰斯特了,为什么呢?因为在其他的这个文件里边哈,你看已经有一个叫泰斯特,你看人家在这里面是不是已经有一个泰斯特莱雅,对吧? 好,那么在这个中间你看是不是又有一个太似的,其实在这里边呢,他给你写了一个单词,看到没?这里面是不是有一个单词呀?对吧?这个单词什么意思?哎,这个单词呢,今后看到的时候要知道哈,他是代表重复的意思,对吧?好,你重复定义这个类名啊,那么 这里边呢,是不允许这个类名重复的,我们后面会给你详细介绍,现在呢,先去在底下啊,先去写一个一,好,好,这样是不是就不重复了,对吧? 就跟你这里面的这个太死了,不重复了啊,虽然讲他们不在一个文件里面呢,他里边也是不允许这个名称重复,我们后边呢会有这个解决方案。现在先别管他,我们来先去写个一,先去管好我们自己 如何去创建这个对象。好,那消耗之后呢?我们写上一个灭重序这个入口,对吧?好,消耗之后我们是不是就开始去创建对象了呀?对吧?好,创建对象,我们说说使用一个六观念字,后面跟上一个类名啊,对吧?好,跟上另一名呢?我们就跟上一个道格。 好,那现在来给你写。好,写好之后是不来去接触一下,来写上我们的这个道个一,哎,我们这个一二,哎,这条狗,那么这条狗一开始的时候呢,里边的这些属性,这些行为是不都没有啊?对不对?好, 那我们呢要去设置这个对象的状态啊,就是设置这个对象的这个状态,对吧?好,设置状态是不是就是你的这个名称到个一这个名 名称,你的一个内幕,你叫什么名字啊?哎,你在这个旁边来去给他设计个名称。好,那我们呢在另一边呢给你设计一个这个旺财一号啊,来,在这个里面呢写上一个旺财一号,就是你狗的一个名称叫旺财一号, 那么这个旺财一号,哎,你里边的这个倒个一啊,哎,你的这个品种是什么品种呢?来里边写一个太婆,对吧?好,那么这个品种呢?哎,我们呢就给你一个品种啊,哎,给一个二哈。好,那么这个是旺财一号,哎,他的这个品种是一个二哈的吧?好,那他这个颜色呢?来 这个倒个一啊,来倒个一呢?然后你这个卡了,卡了呢?你是不是来去给他设计一个颜色呀,对吧?好,那么他这个颜色呢?哎,我们呢就给他一个黑色啊。 ok, 写好,那 你看现在啊,你想去让这个道个,哎,就是我们的这个旺财一号啊,让他来去吃东西,对吧?好,那你看你掉这个方法的时候是不要求你传一个纸给他,你想让他吃什么呀?对不对? 好,你就在这一般呢来去给他哎吃一个这个食物,哎,那么这个食物什么类型的呢?你是不是来去定义的是滋补啥类型底下呢?要去给他一个滋补着太阳,对吧?好,那 在这里边呢,我们呢就让这个旺财一号呢,让他在里边呢来去吃鸡。好,那么让他吃鸡啊,好,那,哎,这里边运行的时候,你看啊,在这里边运行的时候,你看里边打印的应该是什么?是不是名称为这个旺财一号,品种是这个二哈,颜色是黑色的,哎, 他就开始去吃鸡去了呀,对吧?好,是不是他的这个旺财一号就开始去吃鸡了,对吧?好,那这中间呢,我给你加一个空格吧,好,这里面呢?这太挤了啊。 ok, 来这中间来,再去运行一下啊,来点击这个位置啊,点击运行,运行 的时候呢?哎,这样就好看一点了啊,就是没那么挤了。好,你看啊,哎,这个地方是名称是旺财一号,品种呢是这个二哈,颜色呢?是这个黑色,是不?旺财一号开始去吃鸡去了呀,对吧?好,那这个是第一个对象,那么我们有了这个类之后,我们是不是可以去创建很多的这个对象呀,对吧?来,我们又去 超你一个对象,来一个倒个,倒个冲奶,哎,在这个地方呢,是不是又一个对象呀?对吧?好,那写上一个倒个这个类型,好,就把这个类型的写到这里,这是,哎,第二条狗是不是倒个二啊?对吧?然后你的一个内幕呢?来,等于,等于说,哎, 这里边的这个纸呢?来,去给你写上一个 wc, 一个旺财二号。来这边给你写上一个旺财二号啊,然后你第一个旺财二号,你的一个品种是什么样子的?来,里面是一个太太啊,对吧?好,太太。来给你写上一个泰迪, ok, 那么这里边呢给你写好,写好之后呢来这个刀个二。第二条狗啊,哎,你的一个这个颜色呢?点上,哎,点上这个颜色啊,咔了咔了。之后呢来给你写上一个黄色,泰迪一般都很黄啊,好,给它写到这里边来, 写到这当中去写上一个黄色,好,那么这个呢我们就给你写好,写好之后呢,然后,哎,让第二条狗让你呢也开始去一躺,好, 然后你吃什么呢啊?上面是吃鸡,对吧?哎,你呢?你呢?只能吃鸡蛋啊,来,我们把这个鸡蛋呢给你写到这里边。好,那我们看一下啊,在中间呢,我们打一个分隔线。在这个地方呢打一个分隔线啊,好,打一个分隔线。之后呢,你看一下这两个狗两个对象啊,他是不是做的这个行为是不一样的呀?对吧? 啊,就是有一个累之后呢,我可以去生产出很多的这个对象,然后在里边的每一个对象是不是都有自己的这个特征行为啊?对吧?好,第一个呢名称旺财一号,他的品种呢?是二哈,颜色呢是黑色,是不?旺财一号,他是吃鸡啊,对吧?好,吃什么?是不是由你自己在具体这个业务场景里面来决定啊,对吧? 好,那底下旺财二号呢品种是这个泰迪,颜色呢?是黄色,他是不是只能吃鸡蛋啊?对不对?好,那就是。哎,关于我们的这个创建对象,我们呢根据一个需求,就是你先去描述一个例,那 它里面的状态,你是不是用这个成员变量,用这个成员变量来表示里边的行为,是不是使用这个方法来表示啊?对吧?好,你想去创建对象的来就可以去使用这个道格,这种 可以去使用这种形式。六,跟上一个类名来去创建个对象。哎,是不是可以去创建很多的这个对象呀?对吧?有了一个类之后呢,就可以去实力化出很多的对象啊,那这个呢,就是我们对象创建的一个过程啊,我们呢又去给你加强了一下啊,好,这一节呢。

大家好,这节呢主要给大家讲的是我们在一个类的啊标准写法, 那么一个基本类的标准写法呢,首先是由我们的类进行创建,创建好类之后呢,首先有成元变量 构造方法,还有我们的无餐构造,有餐构造还有我们的成员方法,那成员方法呢,在这边我们提供了 get 和我们的, 那么在这边呢给成员变量复制的方式呢?首先由我们的无餐构造啊,加塞也可以使用我们的代餐构造, 那么所以说在这边呢,这是我们的一个标准代码的一个写法,那么下面呢,首先我们来看一下 这个一个基本类型标准代码的一个案例,那么在这一块呢,我们首先啊以学生类为例啊,来大家看一下。 首先呢在这边啊,我们的这一块呢是一个学生,学生呢首先有名字,还有我们的年龄,那么学生呢?首先我们上面这种呢,哎,大家看到这个结果呀,是一个闹, 那这时候呢,我们可以在这边来一个什么啊, s 一点干什么?晒晒我们的名字, 比如这个名字呢,我们给他起个啊,叫什么呢?小花对吧? 小华啊,这个屋,哎,这个小华啊,小华。 好了,这个名字设置好之后呢 s 一点三,再来一个 a 字,那这个年龄呢?比如说十五,那这时候呢,我们的这个 s 一呢,他是不是就有小花和十五了? 所以这一块呢,这就是我们的信息。那么当我们在这边洗完这一块之后啊,大家针对这个手机呢啊,可以啊进行一个测试, 那么手机呢,首先他这边呢有我们的品牌 prad, 还有我们的价格叫做 prass, 对吧?所以说大家呢可以在这边呢进行测试, 那么在这一块啊,一定要注意,首先呢目前呢,呃代码呢,是为了利息的一个规范啊,所以说给成 原复制的两种方式呢,可以只写一种,那么如果不单独获取数据呢,可以不写我们的盖叉叉,那么大家可能说,哎,那我不单独写怎么办?你们是不是有一个哎,可以 书写全部的啊,是不是这一个代码就可以了,那么这一块呢就是我们的信息, 那么在类进行创建时,首先呢他需要先把类啊,先加载我们 cq 等的点克拉斯啊,加载在内存中, 那么这一块呢,在讲内存时我给大家说过,对吧?那么在我们在空间呢,会开辟一个 s, 比如说把它开辟出来,然后呢再对我们对象啊的成语 流变量进行数字化时呢,首先需要我们的啊,这个妞十六的,那么妞十六的呢,在这边呢,他是一个空构造,所以说在这边呢,他具体也没有进行复制, 那么对学生对象的成员变量进行写四处罚字,首先在这一块呢,哎,我们只有通过我们的 get 才能得到,那么通过我们构造方法 对象的成员啊,变量的父子啊,还有学生对象,说实话完毕啊,就是把对象的地址呢,其实父子给来是, 所以在这边呢,我们类的一个初始化过程呢啊,基本就是这样, 谢谢大家。

抓弯一分钟三种方式创建 stream 流对象。首先创建一个数组, 然后将这个数组转换为 list 集合, 然后使用集合对象的 stream 静态方法创建 stream 流对象,然后我们可以使用这个 stream 对象便利元素, 然后运行看看效果, 可以看到元素已经便利出来了。咱们再来看一下第二种方法,使用 stream 接口的 up 静态方法创建 stream 牛对象, 然后再次打印看看效果, 可以看到结果正常打印了。然后再来看一下第三种方法,使用 race 类中的静态方法创建 stream 牛对象, 然后再打印看看效果, 结果正常打印出来了。这三种方法你学会了吗? nice。