热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java8Stream超过了订单的集合一致性

如何解决《Java8Stream超过了订单的集合一致性》经验,为你挑选了2个好方法。

据我所知,Set in java是一个无序集合,迭代器将按照其选择的某个顺序处理项目(我可能在这里错了),但确保它处理集合中的所有元素.

在Java8中,集合中的stream()API已经引入了跳过和限制功能.所以我想知道从流处理的项目的顺序是否保持相同,无论我开始流的次数或每次都是随机的?如果在流之间修改集合,订单会改变吗?

可能是无关紧要但我在这里提出问题:现在遇到问题,我有一套2000或者其他什么东西在创建后不会被修改,我正在进行50个批量操作,涉及每个批次的网络调用.我有一个启动参数,每次调用后增加50.如果我在我的Set上使用一个带有"start"的流作为每个批处理的skip参数,那么它对于每个批处理都是一个新流吗?因此,流程的顺序保持不变.显然,我不会多次相同的条目,更重要的是我不会错过任何条目.最简单的事情对我来说是一个Arraylist但我想知道我是否真的需要创建一个集合.



1> Eugene..:

让我们从这里的例子开始吧.首先,我认为这是显而易见的:

List wordList = Arrays.asList("just", "a", "test");

    Set wordSet = new HashSet<>(wordList);

    System.out.println(wordSet);

    for (int i = 0; i <100; i++) {
        wordSet.add("" + i);
    }

    for (int i = 0; i <100; i++) {
        wordSet.remove("" + i);
    }

    System.out.println(wordSet);

输出将显示不同的"顺序" - 因为我们已经使容量更大(通过1-100添加)并且条目已经移动.他们仍然在那里 - 但是以不同的顺序(如果可以称为顺序).

所以,是的,一旦你修改Set了流之间的操作,"订单"可能会改变.

既然你说post创建Set将不会被修改 - 在当前的实现(无论是什么)下,订单目前保留.或者更确切地说,它不是内部随机化的 - 一旦条目被放入Set.

但这绝对不是一个人依赖的东西.事情可能会在没有通知的情况下发生变化,因为合同被允许这样做 - 文档并没有对任何订单做出任何保证 - Set毕竟这是关于唯一性的.

举个例子来说明jdk-9 Immutable Set并且Map 有一个内部随机化,"order"将从run到run改变:

Set set = Set.of("just", "a", "test");
System.out.println(set);

允许打印:

 [a, test, just] or [a, just, test]

编辑

以下是随机化模式的样子:

/**
 * A "salt" value used for randomizing iteration order. This is initialized once
 * and stays constant for the lifetime of the JVM. It need not be truly random, but
 * it needs to vary sufficiently from one run to the next so that iteration order
 * will vary between JVM runs.
 */
static final int SALT;
static {
    long nt = System.nanoTime();
    SALT = (int)((nt >>> 32) ^ nt);
}

这是做什么的:

花费很长的时间,将前32位与最后32位进行异或,从该长度取最后32位(通过强制转换为int).使用XOR是因为它具有50%的零和1分布,因此它不会改变结果.

如何使用(Set例如,对于两个元素):

// based on SALT set the elements in a particular iteration "order"
if (SALT >= 0) {
   this.e0 = e0;
   this.e1 = e1;
} else {
   this.e0 = e1;
   this.e1 = e0;

我对jdk9内部随机化部分的猜测,最初取自这里,相关部分:

最后的安全功能是不可变Set元素和Map键的随机迭代顺序.HashSet和HashMap迭代顺序一直未指定,但相当稳定,导致代码无意中依赖于该顺序.当迭代顺序发生变化时,这会导致事情中断,这种情况偶尔会发生.新的Set/Map集合将其运行的迭代顺序更改为运行,希望在测试或开发早期清除顺序依赖性

所以它基本上是打破所有依赖于Set/的订单的代码Map.当人们从java-7迁移到java-8并且依赖于HashMap的顺序时,同样的事情发生了LinkedNode,由于TreeNodes的引入,这是不同的.如果你留下这样的功能并且人们依赖它多年 - 很难将它删除并执行一些优化 - 比如HashMap转移到TreeNodes; 因为现在你被迫保留这个命令,即使你不想这样做.但这显然只是猜测,请这样对待它


@Eugene你对随机化动机的猜测是正确的.我记得当时在core-libs dev邮件列表上阅读它.即使是OpenJDK测试代码也有很多这些依赖项,而且要解决这个问题还有一些工作要做.他们想避免再次落入同一个陷阱.
关于迭代顺序的很好的答案,但是一旦流是无序的,强调流上的`skip`和`limit`无论如何都没有绑定到迭代顺序也是很重要的.
@FedericoPeraltaSchaffner我编辑了代码以展示它是如何实现的.
@FedericoPeraltaSchaffner的&#39;为什么&#39;并不容易和老实说我只能想到更好地适应规范的情况(说不保证订单)......
@FedericoPeraltaSchaffner那里还有一段非常有趣的代码,*至少*对我来说.`ImmutableCollections.SetN` - 如何选择数组中的插槽...

2> Holger..:

这里有两个方面.正如尤金正确指出的那样,你不能假设一个HashSet迭代顺序保持不变 - 没有这样的保证.

但另一方面是StreamSpliterator不报告ORDERED特征时不需要维持迭代顺序的实现.

换句话说,如果流是无序的,skip(1)则不需要跳过第一个元素,因为没有"first"元素,而只是跳过一个元素.

虽然流不太可能实现随机化,但它们试图利用特征来最小化工作.一个看似合理的情况是,一个Stream实现将处理skip(n)一个无序但SIZED源,就像这样limit(size-n)也会有效地跳过n个元素,而工作量更少.

这样的优化可能不会在今天发生,但在下一个版本中,即使在HashSet迭代顺序没有改变的情况下也会破坏批处理场景.


优点!我没有想到它,但它很有道理.
推荐阅读
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 预备知识可参考我整理的博客Windows编程之线程:https:www.cnblogs.comZhuSenlinp16662075.htmlWindows编程之线程同步:https ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • Android Studio Bumblebee | 2021.1.1(大黄蜂版本使用介绍)
    本文介绍了Android Studio Bumblebee | 2021.1.1(大黄蜂版本)的使用方法和相关知识,包括Gradle的介绍、设备管理器的配置、无线调试、新版本问题等内容。同时还提供了更新版本的下载地址和启动页面截图。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了在MFC下利用C++和MFC的特性动态创建窗口的方法,包括继承现有的MFC类并加以改造、插入工具栏和状态栏对象的声明等。同时还提到了窗口销毁的处理方法。本文详细介绍了实现方法并给出了相关注意事项。 ... [详细]
  • Postgresql备份和恢复的方法及命令行操作步骤
    本文介绍了使用Postgresql进行备份和恢复的方法及命令行操作步骤。通过使用pg_dump命令进行备份,pg_restore命令进行恢复,并设置-h localhost选项,可以完成数据的备份和恢复操作。此外,本文还提供了参考链接以获取更多详细信息。 ... [详细]
author-avatar
手机用户2702935165
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有