【问题标题】:Function .contains() not working in Groovy on expected way函数 .contains() 在 Groovy 中无法按预期方式工作
【发布时间】:2018-10-10 16:12:23
【问题描述】:

我正在尝试使用 Groovy 编程语言检查 number 是否是列表的成员。

我有这段代码:

List<Long> list = [1, 2, 3]
Long number = 3

println(list.contains(number))​

预期的输出是true,但我得到的结果是false

有人解释一下吗?

【问题讨论】:

  • 你尝试过原始long吗?
  • 我知道如何处理这个问题,但我更感兴趣的是为什么这不起作用。

标签: java groovy contains


【解决方案1】:

泛型类型参数在运行时不具备。检查这个:

List<Long> list = [1, 2, 3]
list.each{println it.getClass()}

哪些打印:

class java.lang.Integer
class java.lang.Integer
class java.lang.Integer

真正的混淆是由.equals== 实现之间的奇怪行为差异引起的:

Long.valueOf(3).equals(Integer.valueOf(3))
===> false
Long.valueOf(3) == Integer.valueOf(3)
===> true

List.contains 似乎在使用.equals,它检查参数的类,从而解释了为什么强制元素类型为Long 可以解决问题。

因此,在这种不确定性中,我认为唯一确定的是 Groovy 的 == 执行执行了最直观和可预测的比较。所以我将检查更改为:

boolean contains = list.grep{it == 3L} //sets value to true if matches at least 1

当人们不必了解与文字相关的数据类型时,它会有所帮助:

def ints = [1, 2, 3]
def longs = [1L, 2L, 3L]

boolean found1 = ints.grep{it == 3L}
boolean found2 = ints.grep{it == 3}
boolean found3 = longs.grep{it == 3L}
boolean found4 = longs.grep{it == 3}

println found1
println found2
println found3
println found4

任何人都想要的:

true
true
true
true

【讨论】:

    【解决方案2】:

    您应该为 long 使用特殊的文字值:1L 而不是 1。

    List<Long> list = [1L, 2L, 3L]
    Long number = 3L
    

    1 是一个整数。 1L很长。

    【讨论】:

    • 我明白了,但对我来说很奇怪的是,如果我声明 Long-s 列表,它们将不会被识别为 Long-s
    • 我同意这是出乎意料的(我也来自 Java 背景。)请注意,这将按您的预期工作:list.any(number)
    • 这就是泛型在 JVM 中的实现方式。您可以使用 GroovyConsole 或调试器来检查实际列表。类型为ArrayList。元素类型的信息丢失。你甚至可以写List&lt;String&gt; list = [1L, 2L, 3L],没关系。
    猜你喜欢
    • 2015-01-28
    • 2014-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-15
    • 2018-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多