Streams

  • 原稿作者:
    shekhargulati
  • 译者: leege100
  • 状态: 完成

在第二章中,大家学习到了lambda表明式允许我们在不创建新类的场所下传递行为,从而帮衬大家写出到底简单的代码。lambda表明式是一种简易的语法结构,它通过动用函数式接口来扶持开发者简单明了的传递意图。当使用lambda表达式的计划性思想来计划API时,lambda表明式的精锐就会得到反映,比如我们在第二节啄磨的利用函数式接口编程的APIlambdas
chapter

Stream是java8引入的一个重度使用lambda表明式的API。Stream使用一体系似用SQL语句从数据库查询数据的直观模式来提供一种对Java集合运算和表达的高阶抽象。直观意味着开发者在写代码时只需关注他们想要的结果是哪些而无需关注实现结果的切实可行措施。这一章节中,大家将介绍为啥大家需要一种新的数码处理API、Collection和Stream的不同之处以及哪些将StreamAPI应用到大家的编码中。

本节的代码见 ch03
package
.

假若有机会,你会愿意和机器人嘿嘿嘿吗?

缘何我们需要一种新的数额处理抽象概念?

在我看来,紧要有两点:

  1. Collection API
    不能提供更高阶的结构来询问数据,由此开发者不得不为贯彻多数零星的职责而写一大堆样板代码。

2、对聚集数据的并行处理有肯定的限定,咋样运用Java语言的面世结构、怎么样高效的处理数据以及怎么着迅速的出现都需要由程序员自己来合计和实现。

先来插播一则消息:爱尔兰马尼拉某家妓院,近年来启用一个所有32E罩杯“性爱机器人”Passion
Dolly ,据说大受主顾欢迎,接客100+,堪称该院红牌!上图我们感受一下。

Java 8往日的数额处理

翻阅下边这一段代码,猜猜看它是拿来做怎么着的。

public class Example1_Java7 {

    public static void main(String[] args) {
        List<Task> tasks = getTasks();

        List<Task> readingTasks = new ArrayList<>();
        for (Task task : tasks) {
            if (task.getType() == TaskType.READING) {
                readingTasks.add(task);
            }
        }
        Collections.sort(readingTasks, new Comparator<Task>() {
            @Override
            public int compare(Task t1, Task t2) {
                return t1.getTitle().length() - t2.getTitle().length();
            }
        });
        for (Task readingTask : readingTasks) {
            System.out.println(readingTask.getTitle());
        }
    }
}

地点那段代码是用来依照字符串长度的排序打印所有READING类型的task的title。所有Java开发者每一天都会写这么的代码,为了写出这般一个简便的程序,我们不得不写下15行Java代码。可是下边这段代码最大的题材不在于其代码长度,而在于不可能清晰传达开发者的来意:过滤出装有READING的task、遵照字符串的长度排序然后生成一个String类型的List。

近日在看一部英(腐)剧《真实的人类》(豆瓣8.4评分)。名字平平无奇,但这部剧的故事真是细思极恐——讲述在未来世界,人工智能已经至极发达,具有惊人智能的合成人在百忙之中都市中被广泛使用。不过人类与机器人的限度愈发模糊,扣人心弦的争执争执、心情冲击与道德拷问轮番上阵。

Java8中的数据处理

可以像下边这段代码这样,使用java8中的Stream
API来贯彻与地点代码同等的功力。

public class Example1_Stream {

    public static void main(String[] args) {
        List<Task> tasks = getTasks();

        List<String> readingTasks = tasks.stream()
                .filter(task -> task.getType() == TaskType.READING)
                .sorted((t1, t2) -> t1.getTitle().length() - t2.getTitle().length())
                .map(Task::getTitle)
                .collect(Collectors.toList());

        readingTasks.forEach(System.out::println);
    }
}

地点这段代码中,形成了一个由四个stream操作结合的管道。

  • stream() – 通过在接近下边tasks List<Task>的集合源上调用
    stream()主意来创建一个stream的管道。

  • filter(Predicate<T>)
    这多少个操效用来提取stream中匹配predicate定义规则的元素。假若您有一个stream,你可以在它上边调用零次要么反复暂停的操作。lambda表明式task -> task.getType() == TaskType.READING概念了一个用来过滤出所有READING的task的条条框框。

  • sorted(Comparator<T>): This operation returns a stream
    consisting of all the stream elements sorted by the Comparator
    defined by lambda expression i.e. in the example shown
    above.此操作重返一个stream,此stream由拥有遵照lambda表达式定义的Comparator来排序后的stream元素组成,在上边代码中排序的表明式是(t1,
    t2) -> t1.getTitle().length() – t2.getTitle().length().

  • map(Function<T,R>):
    此操作再次来到一个stream,该stream的每个元一向自原stream的各种元素通过Function<T,R>处理后获取的结果。

  • collect(toList())
    -此操作把地方对stream举办各个操作后的结果装进一个list中。

譬如其中就有一幕,表现了合成人在富有激情前后,与人类在相处中发出的神秘关系:机器人把女主人家里收拾得齐刷刷,大人小孩都照顾得很好,甚至孩子都爱上他了。可是某天,女主人却发现她爱人和机器人在嘿嘿嘿……

干什么说Java8更好

In my opinion Java 8 code is better because of following reasons:
在我看来,Java8的代码更好重大有以下几点原因:

  1. Java8代码可以清晰地发挥开发者对数据过滤、排序等操作的意向。

  2. 透过采用Stream
    API格式的更高抽象,开发者表明他们所想要的是什么而不是怎么去得到这个结果。

  3. Stream
    API为数量处理提供一种统一的语言,使得开发者在商量数据处理时有共同的词汇。当多少个开发者啄磨filter函数时,你都会精晓他们都是在进展一个数据过滤操作。

  4. 开发者不再需要为实现数量处理而写的各类规范代码,也不再需要为loop代码或者暂时集结来储存数据的冗余代码,Stream
    API会处理这总体。

  5. Stream不会修改潜在的集结,它是非换换的。

可在男主人的心迹,和机器人嘿嘿嘿,怎么能算出轨吗?!

Stream是什么

Stream是一个在某些数据上的肤浅视图。比如,Stream能够是一个list或者文件中的几行如故其他随意的一个元素体系的视图。Stream
API提供可以顺序表现依然并行表现的操作总和。开发者需要领悟某些,Stream是一种更高阶的抽象概念,而不是一种数据结构。Stream不会蕴藏数据Stream天生就很懒,只有在被应用到时才会履行总结。它同意我们发出无限的数据流(stream
of
data)。在Java8中,你能够像下边这样,非凡轻松的写出一个最好制生成特定标识符的代码:

public static void main(String[] args) {
    Stream<String> uuidStream = Stream.generate(() -> UUID.randomUUID().toString());
}

在Stream接口中有诸如ofgenerateiterate等多种静态工厂方法可以用来创设stream实例。下边提到的generate办法包含一个SupplierSupplier是一个可以用来讲述一个不需要任何输入且会暴发一个值的函数的函数式接口,我们向generate主意中传送一个supplier,当它被调用时会生成一个特定标识符。

Supplier<String> uuids = () -> UUID.randomUUID().toString()

运行方面这段代码,什么都不会生出,因为Stream是懒加载的,直到被选用时才会实施。假使我们改成如下这段代码,我们就会在控制台看到打印出来的UUID。这段程序会一向执行下去。

public static void main(String[] args) {
    Stream<String> uuidStream = Stream.generate(() -> UUID.randomUUID().toString());
    uuidStream.forEach(System.out::println);
}

Java8运行开发者通过在一个Collection上调用stream方法来成立Stream。Stream匡助数据处理操作,从而开发者可以利用更高阶的多少处理社团来抒发运算。

于是乎我也顺手在微信群里抛了个问题——【和机器人嘿嘿嘿算不算出轨】,登时群里炸开了锅。

Collection vs Stream

下边这张表解说了Collection和Stream的不同之处

图片 1

Collection vs Stream

下面我们来探索内迭代(internal iteration)和外迭代(external
iteration)的区别,以及懒赋值的概念。

A君(文案高颜值girl):不算,就像飞机杯一样,我会妒忌飞机杯吗?但如若这么些机器人和安吉拉(Angela)baby一样优质,我就承受不了。

外迭代(External iteration) vs (内迭代)internal iterationvs

地点谈到的Java8 Stream API代码和Collection
API代码的分别在于由何人来控制迭代,是迭代器本身仍然开发者。Stream
API仅仅提供他们想要实现的操作,然后迭代器把这些操作使用到秘密Collection的每个元素中去。当对地下的Collection举行的迭代操作是由迭代器本身决定时,就叫着内迭代;反之,当迭代操作是由开发者控制时,就叫着外迭代。Collection
API中for-each社团的使用就是一个外迭代的例子。

有人会说,在Collection
API中我们也不需要对潜在的迭代器举行操作,因为for-each结构已经替我们处理得很好了,可是for-each社团其实只是是一种iterator
API的语法糖罢了。for-each即便很简短,不过它有局部通病 —
1)只有固有各种 2)容易写出生硬的命令式代码(imperative code)
3)难以并行。

B君(电商帅气boy):假若你是彻头彻尾为了生理需求跟机器人发生关联,那么些时候机器人=飞机杯=飞机杯,当然假如将来的确有性爱机器人,然后那多少个机器人在颜值、技巧等方面已经远超了您的伴侣所能带给您的感受的话,从而导致你只想跟机器人发生性关系,而不找你的配偶的话,这么些话题感觉也是可以谈谈的。(讲真,一个飞机杯、按摩器可以完成的效率,一台机器人不得上天?

Lazy evaluation懒加载

stream表明式在被终极操作方法调用此前不会被赋值总结。Stream
API中的大多数操作会重返一个Stream。这个操作不会做任何的实施操作,它们只会构建这一个管道。看着下边这段代码,预测一下它的输出会是咋样。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = numbers.stream().map(n -> n / 0).filter(n -> n % 2 == 0);

下边这段代码中,我们将stream元素中的数字除以0,我们或许会以为这段代码在运行时会抛出ArithmeticExceptin至极,而实际不会。因为stream表明式唯有在有极限操作被调用时才会被实施运算。假若我们为地点的stream加上终极操作,stream就会被执行并抛出相当。

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = numbers.stream().map(n -> n / 0).filter(n -> n % 2 == 0);
stream.collect(toList());

俺们会拿到如下的stack trace:

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at org._7dayswithx.java8.day2.EagerEvaluationExample.lambda$main$0(EagerEvaluationExample.java:13)
    at org._7dayswithx.java8.day2.EagerEvaluationExample$$Lambda$1/1915318863.apply(Unknown Source)
    at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
    at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:512)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:502)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

C君(产品稳重哥):要看这一个机器人是不是有必然自主发现了,假若暴发自主意识的话,已经可以算作“人”。从而判断标准或者自己是不是把机器人当人看。

使用Stream API

Stream
API提供了一大堆开发者可以用来从集合中询问数据的操作,这一个操作分为两种–过渡操作和终极操作。

紧接操作从已存在的stream上发出另一个新的stream的函数,比如filter,map,
sorted,等。

极端操作从stream上爆发一个非stream结果的函数,如collect(toList())
, forEach, count等。

连片操作允许开发者构建在调用终极操作时才实施的管道。下边是Stream
API的有些函数列表:

<a
href=”https://whyjava.files.wordpress.com/2015/07/stream-api.png"&gt;

图片 2

stream-api

</a>

中等大伙儿还拓展了鸡冻的议论,由于篇幅关系不在这展开。

示例类

在本教程中,我们将会用Task管理类来解释这么些概念。例子中,有一个叫Task的类,它是一个由用户来表现的类,其定义如下:

import java.time.LocalDate;
import java.util.*;

public class Task {
    private final String id;
    private final String title;
    private final TaskType type;
    private final LocalDate createdOn;
    private boolean done = false;
    private Set<String> tags = new HashSet<>();
    private LocalDate dueOn;

    // removed constructor, getter, and setter for brevity
}

事例中的数据集如下,在方方面面Stream API例子中我们都会用到它。

Task task1 = new Task("Read Version Control with Git book", TaskType.READING, LocalDate.of(2015, Month.JULY, 1)).addTag("git").addTag("reading").addTag("books");

Task task2 = new Task("Read Java 8 Lambdas book", TaskType.READING, LocalDate.of(2015, Month.JULY, 2)).addTag("java8").addTag("reading").addTag("books");

Task task3 = new Task("Write a mobile application to store my tasks", TaskType.CODING, LocalDate.of(2015, Month.JULY, 3)).addTag("coding").addTag("mobile");

Task task4 = new Task("Write a blog on Java 8 Streams", TaskType.WRITING, LocalDate.of(2015, Month.JULY, 4)).addTag("blogging").addTag("writing").addTag("streams");

Task task5 = new Task("Read Domain Driven Design book", TaskType.READING, LocalDate.of(2015, Month.JULY, 5)).addTag("ddd").addTag("books").addTag("reading");

List<Task> tasks = Arrays.asList(task1, task2, task3, task4, task5);

本章节暂不探讨Java8的Data 提姆e
API,那里我们就把它当着一个普普通通的日期的API。

但结尾研商的点落在“是否把机器人当人看”地点。因为,随着技术的敏捷前进,人们可以给机器人植入人类的情丝和个性。这时候,机器人就不是简单的“工具”了。

Example 1: 找出装有READING Task的题目,并服从它们的始建时间排序。

先是个例证大家就要实现的是,从Task列表中找出所有正在阅读的职责的题目,并遵照它们的创办时间排序。我们要做的操作如下:

  1. 过滤出所有TaskType为READING的Task。
  2. 遵守成立时间对task举办排序。
  3. 获取每个task的title。
  4. 将取得的那些title装进一个List中。

下面的六个操作步骤可以非凡简单的翻译成下边这段代码:

private static List<String> allReadingTasks(List<Task> tasks) {
        List<String> readingTaskTitles = tasks.stream().
                filter(task -> task.getType() == TaskType.READING).
                sorted((t1, t2) -> t1.getCreatedOn().compareTo(t2.getCreatedOn())).
                map(task -> task.getTitle()).
                collect(Collectors.toList());
        return readingTaskTitles;
}

在地点的代码中,我们使用了Stream API中如下的片段方法:

  • filter:允许开发者定义一个论断规则来从地下的stream中领取符合此规则的部分因素。规则task
    -> task.getType() ==
    TaskType.READING
    意为从stream中选用所有TaskType 为READING的要素。

  • sorted:
    允许开发者定义一个相比较器来排序stream。上例中,大家依照制造时间来排序,其中的lambda表明式(t1,
    t2) ->
    t1.getCreatedOn().compareTo(t2.getCreatedOn())
    就对函数式接口Comparator中的compare函数进行了落实。

  • map:
    需要一个实现了可以将一个stream转换成另一个stream的Function<? super T, ? extends R>的lambda表明式作为参数,Function<?
    super T, ? extends
    R>接口可以将一个stream转换为另一个stream。lambda表明式task
    -> task.getTitle()
    将一个task转化为标题。

  • collect(toList())
    这是一个终端操作,它将富有READING的Task的题目的卷入一个list中。

咱俩得以由此使用Comparator接口的comparing模式和情势引用来将方面的代码简化成如下代码:

public List<String> allReadingTasks(List<Task> tasks) {
    return tasks.stream().
            filter(task -> task.getType() == TaskType.READING).
            sorted(Comparator.comparing(Task::getCreatedOn)).
            map(Task::getTitle).
            collect(Collectors.toList());

}

从Java8起头,接口可以蕴涵通过静态和默认方法来贯彻形式,在ch01已经介绍过了。
方法引用Task::getCreatedOn是由Function<Task,LocalDate>而来的。

上边代码中,大家利用了Comparator接口中的静态帮助方法comparing,此办法需要吸收一个用来领取ComparableFunction用作参数,再次回到一个通过key举办相比较的Comparator。方法引用Task::getCreatedOn
是由 Function<Task, LocalDate>而来的.

咱俩得以像如下代码这样,使用函数组合,通过在Comparator上调用reversed()主意,来丰硕轻松的颠倒排序。

public List<String> allReadingTasksSortedByCreatedOnDesc(List<Task> tasks) {
    return tasks.stream().
            filter(task -> task.getType() == TaskType.READING).
            sorted(Comparator.comparing(Task::getCreatedOn).reversed()).
            map(Task::getTitle).
            collect(Collectors.toList());
}

性爱机器人,早已不是下等的意味娃娃

Example 2: 去除重复的tasks

假如大家有一个有为数不少再一次task的数据集,可以像如下代码这样经过调用distinct形式来轻松的删除stream中的重复的因素:

public List<Task> allDistinctTasks(List<Task> tasks) {
    return tasks.stream().distinct().collect(Collectors.toList());
}

distinct()主意把一个stream转换成一个不含重复元素的stream,它经过对象的equals方法来判断目的是不是等于。依照目的相等方法的判定,倘使六个对象相等就表示有重新,它就会从结果stream中移除。

拥有“全球首款性爱机器人”之称的Harmony仿生机器人,是人工智能和机器人的构成。

Example 3: 遵照创制时间排序,找出前5个处于reading状态的task

limit办法可以用来把结果集限定在一个加以的数字。limit是一个围堵操作,意味着它不会为了拿走结果而去运算所有因素。

public List<String> topN(List<Task> tasks, int n){
    return tasks.stream().
            filter(task -> task.getType() == TaskType.READING).
            sorted(comparing(Task::getCreatedOn)).
            map(Task::getTitle).
            limit(n).
            collect(toList());
}

可以像如下代码这样,同时采纳skip方法和limit措施来创造某一页。

// page starts from 0. So to view a second page `page` will be 1 and n will be 5.
//page从0开始,所以要查看第二页的话,`page`应该为1,n应该为5
List<String> readingTaskTitles = tasks.stream().
                filter(task -> task.getType() == TaskType.READING).
                sorted(comparing(Task::getCreatedOn).reversed()).
                map(Task::getTitle).
                skip(page * n).
                limit(n).
                collect(toList());

它用仿生硅胶材料打造而成,内部有加热器,能模拟出人体体温。(还不会漏气)这款性爱机器人仍可以定制生殖器和更换面孔。

Example 4:总计意况为reading的task的多寡

要收获所有正处在reading的task的数量,大家得以在stream中采用count艺术来赢得,这么些法子是一个巅峰方法。

public long countAllReadingTasks(List<Task> tasks) {
    return tasks.stream().
            filter(task -> task.getType() == TaskType.READING).
            count();
}

有别于传统情趣娃娃死板的脸部及身体,HarmonyAI系统预设12种性格特征:天真、善良、性感等。Harmony最牛的是怀有了上学能力的,与人谈话对答如流,同时还有添加的脸部表情,真实得令人有些傻傻分不清。

Example 5: 非重复的列出富有task中的全体标签

要找出不另行的标签,我们需要上边多少个步骤

  1. 收获每个task中的标签。
  2. 把具有的价签放到一个stream中。
  3. 剔除重复的标签。
  4. 把最后结出装进一个列表中。

第一步和第二步可以因此在stream上调用flatMap来得到。flatMap操作把经过调用task.getTags().stream收获的逐条stream合成到一个stream。一旦我们把装有的tag放到一个stream中,大家就足以经过调用distinct措施来拿到非重复的tag。

private static List<String> allDistinctTags(List<Task> tasks) {
        return tasks.stream().flatMap(task -> task.getTags().stream()).distinct().collect(toList());
}

乘胜岁月积淀,AI系统经过相互可以取得不断学习提高。设想下:假若你买了一个Harmony回家(勿喷,这里不是打广告,打广告也买不起),你会意识你的机器人女友逐步在就学你的习惯,每一日都在变更。也就是说,您可以和机器人谈一场真正的恋爱,而不只是一个发泄性欲的工具

Example 6: 检查是否有所reading的task都有book标签

Stream
API有一对方可用来检测数据集中是否包含某个给定属性的主意,allMatch,anyMatch,noneMatch,findFirst,findAny。要一口咬定是否持有情形为reading的task的title中都包含books标签,可以用如下代码来实现:

public boolean isAllReadingTasksWithTagBooks(List<Task> tasks) {
    return tasks.stream().
            filter(task -> task.getType() == TaskType.READING).
            allMatch(task -> task.getTags().contains("books"));
}

要一口咬定所有reading的task中是否留存一个task包含java8标签,可以透过anyMatch来兑现,代码如下:

public boolean isAnyReadingTasksWithTagJava8(List<Task> tasks) {
    return tasks.stream().
            filter(task -> task.getType() == TaskType.READING).
            anyMatch(task -> task.getTags().contains("java8"));
}

即便您也看过英剧《西部世界》(豆瓣9.2分),里面描述的境况可能就会在不久的未来暴发。随着技术发展,3D打印将能带动很好的触感反馈,就像《西部世界》里的妓女机器人般,能与您谈笑风生,还可以像真人一致拥有温柔的触感,深情的视力,嘿嘿嘿时会时有暴发不可描述的叫声……

Example 7: 成立一个富有title的总览

当你想要创立一个具备title的总览时就足以选拔reduce操作,reduce可以把stream变成成一个值。reduce函数接受一个方可用来连续stream中有着因素的lambda表达式。

public String joinAllTaskTitles(List<Task> tasks) {
    return tasks.stream().
            map(Task::getTitle).
            reduce((first, second) -> first + " *** " + second).
            get();
}

之所以你还会觉得,与机器人谈恋爱,甚至爱上机器人,和她们生存在一齐。这太可笑吗?实际这着实不要不能,反而是进一步近了。

Example 8: 基本类型stream的操作

除开周边的按照对象的stream,Java8对诸如int,long,double等骨干类型也提供了一定的stream。上边一起来看有些主旨类型的stream的例子。

要开创一个值区间,可以调用range方法。range主意成立一个值为0到9的stream,不带有10。

IntStream.range(0, 10).forEach(System.out::println);

rangeClosed格局允许我们创制一个涵盖上限值的stream。由此,下面的代码会时有发生一个从1到10的stream。

IntStream.rangeClosed(1, 10).forEach(System.out::println);

还足以像下边这样,通过在主题类型的stream上拔取iterate模式来创制无限的stream:

LongStream infiniteStream = LongStream.iterate(1, el -> el + 1);

要从一个极致的stream中过滤出所有偶数,可以用如下代码来实现:

infiniteStream.filter(el -> el % 2 == 0).forEach(System.out::println);

可以通过使用limit操作来现在结果stream的个数,代码如下:
We can limit the resulting stream by using the limit operation as
shown below.

infiniteStream.filter(el -> el % 2 == 0).limit(100).forEach(System.out::println);

竟然有人评价,色情产业拯救科技前景

Example 9: 为数组创制stream

可以像如下代码这样,通过调用Arrays类的静态方法stream来把为数组建立stream:

String[] tags = {"java", "git", "lambdas", "machine-learning"};
Arrays.stream(tags).map(String::toUpperCase).forEach(System.out::println);

还可以够像如下这样,遵照数组中一定开端下标和竣工下标来创制stream。这里的苗头下标包括在内,而得了下标不带有在内。

Arrays.stream(tags, 1, 3).map(String::toUpperCase).forEach(System.out::println);

VR 的热潮,来的快去得也快。在成千上万人看来,最能加之 VR
以想象空间的使用场景除了游戏之外,还有让广大“老司机”欲拒还迎的小成人电影。

Parallel Streams并发的stream

运用Stream有一个优势在于,由于stream拔取其中迭代,所以java库可以使得的军事管制处理并发。可以在一个stream上调用parallel主意来使一个stream处于并行。parallel艺术的最底层实现基于JDK7中引入的fork-joinAPI。默认状况下,它会时有爆发与机具CPU数量相等的线程。下边的代码中,我们依据拍卖它们的线程来对将数字分组。在第4节中校学习collectgroupingBy函数,现在临时了然为它能够遵照一个key来对元素举办分组。

public class ParallelStreamExample {

    public static void main(String[] args) {
        Map<String, List<Integer>> numbersPerThread = IntStream.rangeClosed(1, 160)
                .parallel()
                .boxed()
                .collect(groupingBy(i -> Thread.currentThread().getName()));

        numbersPerThread.forEach((k, v) -> System.out.println(String.format("%s >> %s", k, v)));
    }
}

在我的机械上,打印的结果如下:

ForkJoinPool.commonPool-worker-7 >> [46, 47, 48, 49, 50]
ForkJoinPool.commonPool-worker-1 >> [41, 42, 43, 44, 45, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130]
ForkJoinPool.commonPool-worker-2 >> [146, 147, 148, 149, 150]
main >> [106, 107, 108, 109, 110]
ForkJoinPool.commonPool-worker-5 >> [71, 72, 73, 74, 75]
ForkJoinPool.commonPool-worker-6 >> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160]
ForkJoinPool.commonPool-worker-3 >> [21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 76, 77, 78, 79, 80]
ForkJoinPool.commonPool-worker-4 >> [91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145]

并不是各类工作的线程都处理相等数量的数字,可以由此转移系统特性来决定fork-join线程池的数量System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "2")

此外一个会用到parallel操作的例证是,当你像下边这样要处理一个URL的列表时:

String[] urls = {"https://www.google.co.in/", "https://twitter.com/", "http://www.facebook.com/"};
Arrays.stream(urls).parallel().map(url -> getUrlContent(url)).forEach(System.out::println);

一经您想更好的主宰如何时候应该利用并发的stream,推荐您读书由Doug
Lea和其余几位Java大牛写的稿子http://gee.cs.oswego.edu/dl/html/StreamParallelGuidance.html

这点获取了世界名牌成人视频网站Pornhub的表明。依照 Pornhub
最新披露的数码(别问我怎么驾驭的),在VR视频上线的一年内,其网站上提供的
VR 版本成人录像由最初的 30 个扩张到了 2600 多少个,平均日点击量达到了 50
万次。

行业人士也不掩饰,成长内容是有助于VR产业发展的重中之重助推力。

成人产业通讯社 XBiz
曾用多少援助了那一个说法。他们总括出,最近购入了VR设备的人,有 38%
是想用来看成人娱乐内容;而成人网站VRPorn的CE也曾表示,“只要 VR
设备(的行销)增长,我们(的职业)也会增进。”

而基于Google旗下广告服务商Doubleclick数据显示,独立访问量前500名的网站中,有数十个都是成长网站。世界最大色情网站Xvideos每月访问量超越44亿,远超阿里巴巴流量。同时,成人性用玩具在美国的售价已高达5000日币。(小纠结要不要用*给一些网站打码,切记切记!不要乱爬墙上一些奇奇怪怪的网站)

将来学家伊恩(伊恩)·皮尔森曾在某个报告中估摸,性爱机器人10年内就会成为实际,甚至代替人类伴侣。他以为以后性爱机器人会像汽车类产品一样,令人消费大量股本去进货,甚至在2050年完全代替人类之间的性关系。

现实的境况也如同在频频“印证”那位砖家的臆想:

许多性玩具公司近日都在付出基于人工智能技术,通过活动互联网控制的机器人。冲击我们生活的科技还包括,虚拟现实和加强现实技术。不用说未来了,近期戴上AR、VR设备就已经能体会虚拟嘿嘿嘿,很多视频里所讲述的光景更是“指日可待”。

岛国用户试用Oculus 体验性爱VR游戏

当然,并非所有人都会接受性爱机器人

这其间涉及一些伦理、心思及社会范围的争持。

稍许人会持乐观的态度。

她们会以为性爱机器人对社会的进步大有裨益。比如使用性爱机器人后,人们对于性问题会尤其的坦率。性爱机器人仍能够当做性行为大家。对于有性关系有心情问题的人,只需买一个机器人就可以了。还要性爱机器人仍可以协理使用者赶走孤独寂寞感。性爱机器人对于这么些不被关注或是寂寞的人,提供心思上或者性欲上的满意。

但也有点人会质疑,甚至是争持。

开首,一些机器人基金会倡导了探索,学者、专家和女权主义者表示,性爱机器人充满了性别歧视,是一种取悦男性的工具,有可能会潜在力促暴力、性骚扰、强奸等犯罪行为。此外,学术界认为AI性爱机器人会导致更大的社会隔阂,让原来不愿进入或接触社会的人更加自闭。

之所以,和机器人嘿嘿嘿算出轨吗?

回到作品最初抛出来的题目。似乎早就有答案?其实不然。

对此我连续问了身边好多恋人,还专门找来某高端如意套领导品牌相关人员做了个小采访,他的见识不过让我“有点出乎意料”——

“我个人会以为机器人更偏于机器而非人,所以如故会把她归类与性爱器具序列里面,某种程度是飞机杯的科技升级而已。据悉此,我不会认为是出轨,更不会认为是道德沦陷,只要不在公众场馆使用,那么这依旧很正规的行事,无可厚非。

不论是是自个儿要好或者**(品牌),都会认为性是一件相比纯粹的按照原始冲动发生的作业,跟爱未必相关。‘我’未必跟一个人啪啪啪一定是因为爱Ta,也未见得因为爱一个人就要跟Ta啪啪啪。

(还问到性爱机器人普及是否会对避孕套销量有震慑)性器具产业如今这个年都在蓬勃发展,对如意套行业也进献了力量,因为在运用器具的同时,也都是要戴套的,不管是男用仍旧女用,这是必备的清洁常识,也是必要的珍惜自己健康的手腕。”

另外还有位情人的答应更是让我感到震惊,哦不,是触动。

她对与机器人嘿嘿嘿是否算出轨解释说道,“在YP如此便宜方便的一代,她宁愿用机器人也不出去乱搞,这么好的爱人现在哪儿去找?”

拷问灵魂的诚恳话大冒险到了,对于这几个问题,你是怎么看的吗?