Home > Software engineering >  scala: Is collection object mutable?
scala: Is collection object mutable?

Time:07-01

this question has no functional value. Just trying to get a better understanding of scala. All collections inherent Iterable. There is no isMutable method in Iterable. Soliciting input on whether the below isMutable is the most efficient to assess mutability. It seems archaic but couldn't find an alternative other than testing for all mutable collection classes which is not ideal since new mutable classes could be added in the future. (I would define the method using implicit but didn't for simplicity).

import scala.collection.{immutable, mutable}

object IsMutable extends App {
  val mutableMap: mutable.Map[String, Int] = mutable.Map("Apples" -> 4,"Pineapples" -> 1,"Oranges" -> 10,"Grapes" -> 7)
  val immutableMap: immutable.Map[String, Int] = Map("Apples" -> 4,"Pineapples" -> 1,"Oranges" -> 10,"Grapes" -> 7)

  def isMutable[A](obj: Iterable[A]): Boolean = obj.getClass.toString.startsWith("class scala.collection.mutable")

  println(isMutable(mutableMap))
  println(isMutable(immutableMap))
}

CodePudding user response:

I think relying on the class name is not a good approach, although I believe, that the approach I'm proposing is not probably the most elegant/best way to find out if a collection is mutable or not. But you can use this:

import scala.reflect.ClassTag

def isMutable[T](iterable: scala.collection.Iterable[T]): Boolean = 
  iterable.isInstanceOf[scala.collection.mutable.Iterable[T]]

I think it would work fine for most of the types (the weird interface below is because I'm using ammonite as REPL, which is pretty cool :D).

@ val immutableMap = scala.collection.immutable.Map[String, String]() 
immutableMap: Map[String, String] = Map()

@ isMutable(immutableMap) 
res14: Boolean = false

@ val mutableMap = scala.collection.mutable.Map[String, String]() 
mutableMap: mutable.Map[String, String] = HashMap()

@ isMutable(mutableMap) 
res16: Boolean = true

CodePudding user response:

There is an easier way: mutable collections inherit 2 specific traits that allow them to be mutated internally: Growable and Shrinkable. Checking if your collection is an instance of either one of these 2 traits means it is mutable:

val myMap: mutable.Map[String, Int] = mutable.Map(
    "Apples" -> 4,
    "Pineapples" -> 1,
    "Oranges" -> 10,
    "Grapes" -> 7
  )
  val mySet: mutable.Set[Int] = mutable.Set(1, 2, 3)

  val myMap2: Map[String, Int] = Map(
    "Apples" -> 4,
    "Pineapples" -> 1,
    "Oranges" -> 10,
    "Grapes" -> 7
  )
  val mySet2: Set[Int] = Set(1, 2, 3)

  println(myMap.isInstanceOf[mutable.Growable[_]])       // true
  println(myMap2.isInstanceOf[mutable.Shrinkable[_]])    // false
  println(mySet.isInstanceOf[mutable.Shrinkable[_]])     // true
  println(mySet2.isInstanceOf[mutable.Shrinkable[_]])    // false
  • Related