是否有可能在 Java 8 中创建一个通过递归定义的、以惰性方式无限增长的集合?

2023-11-24

我可以创建一个递归闭包:

static IntUnaryOperator fibo;
fibo = 
    (i) -> 
    i<2 ? 1 : fibo.applyAsInt(i-1)+ fibo.applyAsInt(i-2);

但当然,它仅作为示例才有意义。为了有用,这样的集合应该保留已经计数过的元素并 get() 它们而不重新计数。元素的计数应该在第一次需要时以惰性方式进行。因此,任何成员都不必计算多次。通过这种方式,我们将得到一个看起来像递归定义的序列的结构,并且快速且可重用。

当我开始学习 Java 8 时,我认为 Stream 就是这样工作的。但事实并非如此,因为流不能使用两次。

我考虑了以下构建:

IntStream fi;
fi=IntStream.iterate(0, i -> fi[i-1]+fi[i-2]);

但这样它就行不通——我无法通过索引从流中获取项目。另一个问题是,如果我稍后沿着流走,它将被消耗,并且我不能重复使用它。如果我将流复制到 List,它就不再是懒惰的了。

因此,我需要一些可以通过索引来解决的构造。作为fibo(i).

编辑。显然,该解决方案不能是流,因为流不能被使用两次。我不想在每次调用 F(i) 时重复所有计算。


看来你在要求这样的事情:

public class Fibonacci extends AbstractList<BigInteger> {
    @Override
    public Stream<BigInteger> stream() {
        return Stream.iterate(new BigInteger[]{ BigInteger.ONE, BigInteger.ONE },
           p->new BigInteger[]{ p[1], p[0].add(p[1]) }).map(p -> p[0]);
    }
    @Override
    public Iterator<BigInteger> iterator() {
        return stream().iterator();
    }
    @Override
    public int size() {
        return Integer.MAX_VALUE;
    }
    @Override
    public BigInteger get(int index) {
        return stream().skip(index).findFirst().get();
    }
}

可以通过以下方式访问List接口(它没有实现RandomAccess有充分的理由),因此,您可以通过以下方式询问第 n 个值get(n)。请注意,执行get提示您如何获取之后位置的值Integer.MAX_VALUE。只需使用stream().skip(position).findFirst().get().

谨防!这份清单是infinite,正如你所要求的。不要要求它对所有元素进行操作,例如甚至不toString()。但像下面这样的事情将会顺利进行:

System.out.println(new Fibonacci().subList(100, 120));

or

for(BigInteger value: new Fibonacci()) {
    System.out.println(value);
    if(someCondition()) break;
}   

但是,当您必须处理大型元素序列并希望高效地完成时,您应该确保在迭代器或流上工作,以避免O(n²)重复的复杂性get calls.

请注意,我将元素类型更改为BigInteger因为当涉及到斐波那契数列和int or long值类型。即使与longvalue 类型,仅 92 个值后序列就结束,发生溢出。


更新:既然你明确表示你正在寻找一个懒惰的人storage,您可以按如下方式更改上面的类:

public class Fibonacci extends AbstractList<BigInteger> {
    final Map<BigInteger,BigInteger> values=new HashMap<>();

    public Fibonacci() {
        values.put(BigInteger.ONE, BigInteger.ONE);
        values.put(BigInteger.ZERO, BigInteger.ONE);
    }

    @Override
    public BigInteger get(int index) {
        return get(BigInteger.valueOf(index));
    }
    public BigInteger get(BigInteger index) {
        return values.computeIfAbsent(index, ix ->
            get(ix=ix.subtract(BigInteger.ONE)).add(get(ix.subtract(BigInteger.ONE))));
    }

    @Override
    public Stream<BigInteger> stream() {
        return Stream.iterate(BigInteger.ZERO, i->i.add(BigInteger.ONE)).map(this::get);
    }
    @Override
    public Iterator<BigInteger> iterator() {
        return stream().iterator();
    }
    @Override
    public int size() {
        return Integer.MAX_VALUE;
    }
}

I used BigInteger作为这里的键/索引来满足(理论上)无限的要求,尽管我们可以使用long也是所有实际用途的关键。关键点是最初为空的存储:(现在示例性地使用long):

final Map<Long,BigInteger> values=new HashMap<>();

它是用应该结束每个递归的值预先初始化的(除非由于已经计算的值而提前结束):

values.put(1L, BigInteger.ONE);
values.put(0L, BigInteger.ONE);

然后,我们可以通过以下方式请求一个延迟计算值:

public BigInteger get(long index) {
    return values.computeIfAbsent(index, ix -> get(ix-1).add(get(ix-2)));
}

或委托给的流get上述方法:

LongStream.range(0, Long.MAX_VALUE).mapToObj(this::get);

这创建了一个“实际上无限”的流,而上面的完整示例类使用BigInteger理论上是无限的……

The Map将记住序列的每个计算值。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否有可能在 Java 8 中创建一个通过递归定义的、以惰性方式无限增长的集合? 的相关文章

  • 将处理项目移至 Eclipse

    我已经在处理项目上工作了一段时间 现在想将其移至 Eclipse 中 我已经在 Eclipse 环境中安装了 Proclipse 我有很多扩展名为 pde 的文件 然而 Proclipse 文件都以 java 结尾 所有 pde 文件都存在
  • Java,顺序流在哪个线程中执行?

    在阅读有关流的文档时 我遇到了以下句子 attempting to access mutable state from behavioral parameters presents you with a bad choice if you
  • 垂直 ViewPager 中的动画

    我需要垂直制作这个动画ViewPager https www youtube com watch v wuE 4jjnp3g https www youtube com watch v wuE 4jjnp3g 这是我到目前为止所尝试的 vi
  • Java 小程序在 Mac 上闪烁

    这个问题很奇怪 问题并非在每个平台上都会发生 我在使用 MacOSX 的 Google Chrome 中出现了这种情况 但在 Safari 中却没有出现这种情况 对于使用 Windows 的朋友来说 在 Google Chrome 上运行得
  • H2数据库:如何进行加密保护,而不暴露文件加密密钥

    我们在服务器模式下使用Java H2数据库 因为我们不希望用户访问数据库文件 为了对数据库文件添加更多保护 我们计划使用 AES 加密 将 CIPHER AES 添加到数据库 URL 以防存储被盗 但是 每个用户在连接时还需要提供文件保护密
  • 使用 Jena 查询维基数据

    目前 Wikidata 有一个 SPARQL 端点 https query wikidata org https query wikidata org 我想使用 Jena 3 0 1 查询此网站 我使用以下代码 但收到错误消息 端点返回的
  • for循环中更新JLabel的问题

    我的程序的想法是从之前在其他 JFrame 中保存的列表中选择一个名称 我想在标签中一个接一个地打印所有名称 它们之间有很小的延迟 然后停在其中一个名称上 问题是lbl setText String 如果有多个则不起作用setText co
  • Java 中如何验证字符串的格式是否正确

    我目前正在用 Java 编写一个验证方法来检查字符串是否是要更改为日期的几种不同格式之一 我希望它接受的格式如下 MM DD YY M DD YY MM D YY 和 M D YY 我正在测试第一种格式 每次它都告诉我它无效 即使我输入了有
  • 膨胀类 android.support.design.widget.NavigationView 时出错

    我按照 NavigationView 的教程进行操作 但无法解决此错误消息 Error inflating class android support design widget NavigationView 教程链接 https www
  • RxJava android mvp 单元测试 NullPointerException

    我是 mvp 单元测试的新手 我想对演示者进行一个非常基本的测试 它负责登录 我只想断言 view onLoginSuccess 这是演示者代码 public LoginPresenter LoginViewContract loginVi
  • 如何在 spring-data 中强制使用 CrudRepository 进行预加载?

    我有一个实体 其中包含List就是这样lazy默认加载 interface MyEntityRepository extends CrudRepository
  • Java 8 方法签名不一致

    Java 8 为我们提供了具有很长签名的新方法 如下所示 static
  • 开发者环境-如何调用/消费其他微服务

    背景 我的环境 Java Play2 MySql 我在 Play2 gt S1 S2 S3 上编写了 3 个无状态 Restful 微服务 S1 消耗来自 S2 和 S3 的数据 因此 当用户点击 S1 时 该服务会异步调用 S2 S3 合
  • Firebase:用户注册后如何进行电话号码验证?

    所以我知道我可以使用电子邮件验证或电话号码验证 但我想做的是在用户注册或登录后进行电话号码验证 如何连接这两种身份验证方法 最后 Firebase中是否有一个函数可以检查用户是否通过电话号码验证 谢谢 即使用户已通过身份验证 您仍然可以使用
  • java Web应用程序中的日期转换

    String date1 13 03 2014 16 56 46 AEDT SimpleDateFormat sdf new SimpleDateFormat dd MM yyyy HH mm ss z sdf setTimeZone Ti
  • 从 InputStream 中删除换行符

    我喜欢从一个文件中删除所有换行符 对于 n 和 r n java io InputStream 在读取文件时 相应的方法如下所示 param target linkplain File return linkplain InputStrea
  • Java 中序列化的目的是什么?

    我读过很多关于序列化的文章 以及它如何如此美好和伟大 但没有一个论点足够令人信服 我想知道是否有人能真正告诉我通过序列化一个类我们真正可以实现什么 让我们先定义序列化 然后我们才能讨论它为什么如此有用 序列化只是将现有对象转换为字节数组 该
  • Java时区混乱

    我正在运行 Tomcat 应用程序 并且需要显示一些时间值 不幸的是 时间快到了 还有一个小时的休息时间 我调查了一下 发现我的默认时区被设置为 sun util calendar ZoneInfo id GMT 08 00 offset
  • 如何在J2ME中获取数字的幂[重复]

    这个问题在这里已经有答案了 可能的重复 J2ME power double double 数学函数实现 https stackoverflow com questions 2076913 j2me powerdouble double ma
  • 如何使用socket.io发送图像文件(二进制数据)?

    我无法从以下位置发送数据Android Client to NodeJS Server I use Socket IO 客户端 https github com socketio socket io client java我的客户端中的ja

随机推荐

  • 如何在Windows中异步打开文件

    有没有办法在 Windows 中异步打开文件 CreateFile API 函数只有 FILE FLAG OVERLAPPED 允许进一步异步读取和写入 尽管如此 文件的打开似乎是同步的 鉴于它必须访问文件系统 并可能执行昂贵的 IO 操作
  • 使用 fscanf 读取双精度

    我想从文本文件中读取双精度值 例如 31 39 9316476397222 116 113516352222 我两种都试过了 没用 我只能读取前几位十进制数字 例如39 93164 但不是 39 9316476397222 有人知道为什么吗
  • 无需光标即可在 Android Sqlite 中访问大型 BLOB

    Android 的光标窗口大小似乎有 1MB 的限制 这限制了从 SQLite 读取 BLOB 的能力 我知道您可能会说我们不应该将 BLOB 存储在数据库中 但根据定义 BLOB 被视为二进制大对象 如果不需要将它们存储在数据库中 则无需
  • 如何生成多重集的所有排列?

    多重集是一个集合 其中所有元素可能不唯一 如何枚举集合元素之间所有可能的排列 生成所有可能的排列然后丢弃重复的排列是非常低效的 存在各种算法来直接生成按字典顺序或其他类型的排序的多重集的排列 Takaoka 的算法是一个很好的例子 但 Aa
  • 编译后的 .lib 文件对于不同版本的 Microsoft Visual C++ 是否可以互换?

    有些项目为 C 以及可能的 C 不确定 库提供了一组 Windows 二进制文件 例如 请参阅右侧的链接这个 libxml 相关页面 我很确定没有办法在 VC lib 文件和 MinGW GCC a 文件之间进行转换 因此将它们称为 Win
  • 链接器命令失败,架构 i386 的符号未定义

    我正在尝试执行半页卷曲功能 这是我正在使用的代码 import
  • &**this 到底返回什么?

    这是指向调用对象的指针 它返回右值 这是一个指向调用对象的指针的指针 它返回地址的值 这是一个指向调用对象的指针的指针 这是对调用对象的指针的指针的引用 std vector
  • Google OR 工具 - 火车调度问题

    我试图解决的问题有点像这里的员工调度问题 https github com google or tools blob master examples python shift scheduling sat py 然而 有一些事情我被困住了
  • 对于 SQL Server 2005 表来说,多少列过多?

    我有一个请求 允许动态表拥有 1000 列 由我的最终用户随机选择 这对我来说似乎是个坏主意 这是一个可定制的表格 因此它混合了varchar 200 and float列 float 最适合应用程序 c double 类型 该数据库主要是
  • ASP.NET MVC 2 中带有约束的可选路由参数?

    如果我有这样的路线 routes Add new Route controller page new RouteValueDictionary page UrlParameter Optional new RouteValueDiction
  • JavaScript 数字开头为 0

    我只是想理解数字开头有 0 s 的 js 逻辑 例如 var x 09 3 here x 9 3 other example 09 3 9 3 returns true but check this one var x 02 5 Uncau
  • 如何在 Swing 应用程序中混合使用 Java Swing 和 JavaFX?

    我正在开发一个 Java Swing 应用程序 但我还想将 JavaFX 与 Swing 一起使用 有没有任何资源告诉您如何做到这一点 See here 简而言之 现在可以在 Swing 中嵌入 JavaFX 并通过以下方式获得支持JFXP
  • 解释 Swift 迭代器

    关于如何在 Swift 中制作生成器 或者迭代器因为它们在 Swift 中显然是这样称呼的 特别是如果您是该语言的新手 为什么有这么多发电机类型AnyIterator and UnfoldSequence 为什么下面的代码不这样做 它应该从
  • KDoc 中的表?

    我们的 Java DTO 中通常有变更日志 它由 Javadoc 中定义的表组成 Changelog table tr th Version th th Description th tr tr td 2 td td Added field
  • 使用 Dataflow 读取 CSV 标头

    我有一个 CSV 文件 但我事先不知道列名称 我需要在 Google Dataflow 中进行一些转换后以 JSON 格式输出数据 获取标题行并将标签渗透到所有行的最佳方法是什么 例如 a b c 1 2 3 4 5 6 变成 大约 a 1
  • 如何更改 Keras 优化器代码

    我对 Keras 很陌生 所以如果我的查询有点愚蠢 请原谅我 我使用默认方法在系统中安装了 Keras 并且运行良好 我想向 Keras 添加一个新的优化器 以便我可以在 model compile 函数下轻松提及 optimizer my
  • Qt Creator - 如何删除 Clang 代码模型

    几个月前我开始使用 Qt 它很好而且很容易使用 昨晚我更新了它 但有些东西把一切搞乱了 我无法运行 qmake 也不知道如何修复它 所以我卸载并重新安装了它 现在它使用的是 Clang 模型 我不确定以前是否是这样 但我认为不是 现在自动完
  • 从时间跨度中获取整数天数?

    目前我有这个 var x Convert ToString dateTimePicker2 Value Subtract dateTimePicker1 Value int xDays Convert ToInt32 x Substring
  • 使用 Paramiko 单独执行多个相关命令并查明每个命令何时完成

    我正在用 Python 编写一个程序 它必须通过 SSH 与物理目标进行通信 并自动向该目标发送一些命令 用于测试 我首先使用 Paramiko 执行此操作 一切都很完美 直到我必须发送多个命令 例如第二个命令必须在第一个命令的上下文中执行
  • 是否有可能在 Java 8 中创建一个通过递归定义的、以惰性方式无限增长的集合?

    我可以创建一个递归闭包 static IntUnaryOperator fibo fibo i gt i lt 2 1 fibo applyAsInt i 1 fibo applyAsInt i 2 但当然 它仅作为示例才有意义 为了有用