【问题标题】:Override ArrayBuffer.contains() method in Scala在 Scala 中覆盖 ArrayBuffer.contains() 方法
【发布时间】:2017-04-18 23:01:31
【问题描述】:

我是 Scala 新手,我想检查 String 是否存在于 ArrayBuffer[String] 中,但不区分大小写。所以我在想创建一个新类扩展ArrayBuffer[String] 并使用Java String 方法equalsIgnoreCase() 例如:

MyArrayBuffer("smallint", "INt", "varchar").contains("int")

类是这样的:

class MyArrayBuffer[String]() extends ArrayBuffer[String] {
    def containsCaseIns(str: String): Boolean = {
      for (s <- this) {
        if (str.equalsIgnoreCase(s))
          true;
      }
      false;
    }
  }

但我因编译错误而失败"value equalsIgnoreCase is not a member of type parameter String"

那么我该如何解决呢?或者有什么更好的方法吗?

【问题讨论】:

  • 提示:如何在 Scala 中声明泛型类?

标签: java scala


【解决方案1】:

这里没有必要使用子类。您可以使用现有方法轻松实现此功能

val buff = ArrayBuffer("smallint", "INt", "varchar")
buff.exists(_.equalsIgnoreCase("int")) //true

exists 接受一个条件,如果至少有一个元素满足条件,则返回 true。

如果您认为向 ArrayBuffer[String] 添加方法“containsIgnoreCase”更好,您也可以很容易地做到这一点,而无需使用扩展方法进行子类化,有时称为“增强我的库”模式。您可以通过将方法添加到隐式类来实现这一点。

object Extensions {
  implicit class EnhancedStringBuffer(val underlying: ArrayBuffer[String]) extends AnyVal {
      def containsIgnoreCase(elem: String): Boolean = underlying.exists(_.equalsIgnoreCase(elem))
  }
}

现在可以了

 import Extensions._
 ArrayBuffer("smallint", "INt", "varchar").containsIgnoreCase("int") //true

因为它是一种值类型,所以您不会产生任何额外的运行时对象分配成本。您甚至可以使其更通用,使用 GenTraversableOnce[String] 作为底层的类型,然后您可以将此新方法用于任何字符串集合。

请注意,这些方法的运行时间复杂度为 O(n)(一旦找到匹配项就会短路,因此并不总是需要完全遍历)。如果您正在收集大量字符串,并且需要经常进行包含检查,您可能需要完全采用不同的方法。在这种情况下,您只需在输入时将所有条目转换为大写的哈希集可能是您最好的选择。

import scala.collection.mutable

class CaseInsensitiveStrings {

  private[this] val strings = new mutable.HashSet[String]()

  def addString(elem: String) = strings.add(elem.toUpperCase)

  def contains(elem: String) = strings.contains(elem.toUpperCase)

}

如果您只有一组相对较小的字符串,或者您不经常进行包含检查,那么这可能不值得做,但如果是这种情况,哈希集将允许对大量字符串进行有效查找.这意味着您不能存储多个相同的不区分大小写的字符串,因此如果需要,您将进行一些更改。您可以添加您认为必要的任何其他方法或特征,但要小心确保所有条目都是大写的不变量成立。

【讨论】:

    【解决方案2】:

    关于为什么你的类无法编译的一些背景信息:

    您的类定义了一个名为 String 的类型参数,它隐藏类 java.lang.String

    如果您将其编写为,您的类将编译

    class MyArrayBuffer() extends ArrayBuffer[String] {
        def containsCaseIns(str: String): Boolean = {
          for (s <- this) {
            if (str.equalsIgnoreCase(s))
              true;
          }
          false;
        }
      }
    

    【讨论】:

      【解决方案3】:

      这会起作用(a 是你的缓冲区):

      a.filter(_.equalsIgnoreCase("int")).length > 0
      

      【讨论】:

      • 使用a.exists(_.equalsIgnoreCase("int"))可能更直接
      • 它可以工作,但它总是检查equalsIgnoreCase 是否有a所有 元素,而不是在它返回true 的第一个元素处停止。
      • 是的,最好使用a.exists(_.equalsIgnoreCase("int"))
      猜你喜欢
      • 2015-02-25
      • 1970-01-01
      • 2015-10-31
      • 2021-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-07
      • 1970-01-01
      相关资源
      最近更新 更多