覆盖Scala中的ArrayBuffer.contains()方法

时间:2017-04-18 12:05:22

标签: java scala

我是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"

而失败了

那我该怎么办呢?或者有更好的方法吗?

3 个答案:

答案 0 :(得分:2)

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

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

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

如果您认为添加方法更好[&34; containsIgnoreCase&#34;对于ArrayBuffer [String],你可以很容易地做到这一点,而无需使用扩展方法进行子类化,有时也称为&#34;增强我的库&#34;图案。您可以实现这一点,即将方法添加到隐式类中。

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)

}

如果你只有一个相对较小的字符串集,或者你不经常这样做包含检查,这可能不值得做,但如果是这样的话,一个hashset将允许有效查找甚至大套的字符串。这意味着您不能存储相同的不区分大小写的字符串的倍数,因此如果您需要,您可以稍微改变一下。您可以添加您认为必要的任何其他方法或特征,但要小心确保所有条目都是大写的不变量。

答案 1 :(得分:1)

有关您的类无法编译的原因的一些背景信息:

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

如果您将其编写为

,您的课程将编译
class MyArrayBuffer() extends ArrayBuffer[String] {
    def containsCaseIns(str: String): Boolean = {
      for (s <- this) {
        if (str.equalsIgnoreCase(s))
          true;
      }
      false;
    }
  }

答案 2 :(得分:0)

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

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