为什么 Kotlin 的 generateSequence 在下面的示例中返回了太多项?

如何解决为什么 Kotlin 的 generateSequence 在下面的示例中返回了太多项?

我正在根据 cron 表达式计算瞬间的投影,并将它们作为 Sequence 返回。这是课程:

// (package omitted)

import org.springframework.scheduling.support.CronExpression
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.zoneddatetime
import java.time.temporal.ChronoUnit

class Recurrence(val cronExpression: String) {
    private val cron = CronExpression.parse(cronExpression)

    fun instants(
        fromInclusive: LocalDate = LocalDate.Now(),toExclusive: LocalDate = fromInclusive.plusMonths(1)
    ): Sequence<LocalDateTime> = instants(fromInclusive.atStartOfDay(),toExclusive.atStartOfDay())

    fun instants(
        fromInclusive: LocalDateTime = LocalDateTime.Now(),toExclusive: LocalDateTime = fromInclusive.plusMonths(1)
    ): Sequence<LocalDateTime> {
        return generateSequence(cron.next(fromInclusive.minusNanos(1))) {
            if (it.isBefore(toExclusive)) {
                cron.next(it)
            } else {
                null
            }
        }
    }

}

以下测试失败,因为第一个断言为假:返回的列表末尾有一个额外的、意外的元素。

// (package omitted)

import java.time.LocalDate
import java.time.Month
import kotlin.test.Test
import kotlin.test.assertEquals

class RecurrenceTest {
    @Test
    fun testInstants() {
        val r = Recurrence("@daily")
        val from = LocalDate.of(2021,Month.JANUARY,1)
        val forDays = 31
        val instants = r.instants(from,from.plusDays(forDays.toLong())).toList()
        assertEquals(forDays,instants.size)
        (1..forDays).forEach {
            assertEquals(from.plusDays(it.toLong() - 1).atStartOfDay(),instants[it - 1])
        }
    }
}

如果我通过构建 ArrayList 来重新实现,它会按预期工作:

// new collection-based methods in Recurrence
    fun instantsList(
        fromInclusive: LocalDate = LocalDate.Now(),toExclusive: LocalDate = fromInclusive.plusMonths(1)
    ): List<LocalDateTime> = instantsList(fromInclusive.atStartOfDay(),toExclusive.atStartOfDay())

    fun instantsList(
        fromInclusive: LocalDateTime = LocalDateTime.Now(),toExclusive: LocalDateTime = fromInclusive.plusMonths(1)
    ): List<LocalDateTime> {
        val list = arraylistof<LocalDateTime>()
        var it = cron.next(fromInclusive.minusNanos(1))
        while (it !== null) {
            if (it.isBefore(toExclusive)) {
                list.add(it)
                it = cron.next(it)
            } else {
                break
            }
        }
        return list
    }

测试中要更改的一行是使用新方法

val instants = r.instantsList(from,from.plusDays(forDays.toLong()))

为什么基于序列的实现比基于列表的实现多返回一个元素?

解决方法

如果我正确阅读了您的代码,则在列表实现中您检查是否 it.isBefore(toExclusive),然后才将其添加到列表中。在序列实现中,您执行相同的检查 it.isBefore(toExclusive),然后将 next 项添加到序列中。

与第一项类似。在列表实现中,您检查 cron.next(fromInclusive.minusNanos(1)) 是否满足要求。在顺序实现中,您总是添加它。

,

谢谢,@broot——你发现了这个问题。刚刚又拍了一组眼球。正确的序列实现是

    fun instants(
        fromInclusive: LocalDateTime = LocalDateTime.now(),toExclusive: LocalDateTime = fromInclusive.plusMonths(1)
    ): Sequence<LocalDateTime> {
        val seed = cron.next(fromInclusive.minusNanos(1))

        return generateSequence(seed) {
            val next = cron.next(it)

            if (next.isBefore(toExclusive)) {
                next
            } else {
                null
            }
        }
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?