Scala convert ArrayList in Map[String, Any] to Seq - java

I'm trying to read in a .yaml file into my Scala code. Assume I have the following yaml file:
animals: ["dog", "cat"]
I am trying to read it using the following code:
val e = yaml.load(os.read("config.yaml")).asInstanceOf[java.util.Map[String, Any]]
val arr = e.getOrDefault("animals", new Java.util.ArrayList[String]()) // arr is Option[Any], but I know it contains java.util.ArrayList<String>
arr.asInstanceOf[Buffer[String]] // ArrayList cannot be cast to Buffer
The ArrayList is type Any, so how do I cast to a Scala Collection e.g. Buffer? (Or Seq, List...)

SnakeYaml (assuming what you're using) can't give you a scala collection like Buffer directly.
But you can ask it for ArrayList of string and then convert it to whatever you need.
import scala.jdk.CollectionConverters._
val list = arr.asInstanceOf[util.ArrayList[String]].asScala
results in:
list: scala.collection.mutable.Buffer[String] = Buffer(dog, cat)

Another option you have is to define the model of you configuration, for example:
class Sample {
#BeanProperty var animals = new java.util.ArrayList[String]()
}
The following will create an instance of Sample:
val input = new StringReader("animals: [\"dog\", \"cat\"]")
val yaml = new Yaml(new Constructor(classOf[Sample]))
val sample = yaml.load(input).asInstanceOf[Sample]
Then, using CollectionConverters in Scala 2.13, or JavaConverters in Scala 2.12 or prior, convert animals into a Scala structure:
val buffer = sample.getAnimals.asScala
Code run at Scastie.

Related

How to covert a Java collection into a Kotlin Sequence (and vice versa) in Java?

I am implementing a Kotlin interface in Java which expects me to return a Sequence<T>.
How can I convert a Java collection into a Kotlin Sequence? Conversely, how can I convert a Kotlin Sequence into a Java collection?
Here are some conversions:
val javaList = java.util.ArrayList<String>()
javaList.addAll(listOf("A", "B", "C"))
// From Java List to Sequence
val seq = sequenceOf(*javaList.toTypedArray())
// or
val seq2 = javaList.asSequence()
// Sequence to Kotlin List
val list = seq.toList()
// Kotlin List to Sequence
val seqFromList = sequenceOf(*list.toTypedArray())
// or
val seqFromList2 = list.asSequence()
// Sequence to Java List
val newJavaList = java.util.ArrayList<String>().apply { seqFromList.toCollection(this) }
// or
val newJavaList2 = java.util.ArrayList<String>()
newJavaList2.addAll(seqFromList)
Since the Kotlin code gets run from Java, it gets a bit trickier.
Let's try to recreate the scenario:
Kotlin:
interface SequenceInterface {
fun foo(list: List<Int>) : Sequence<Int>
}
If you inspect Kotlin code, you will discover that there's no particular implementation of the Sequence interface. So, in your case, you need to implement it by yourself (just like Kotlin is doing when calling asSequence:
public class Foo implements SequenceInterface {
#NotNull
public Sequence<Integer> foo(final List<Integer> list) {
return () -> list.listIterator();
}
}
and then you can start using it in Java:
new Foo().foo(Arrays.asList(42))
Keep in mind that all useful methods will be gone since they are implemented as Kotlin extensions.
Want to convert to List? In plain Java, just reiterate:
ArrayList<Integer> list = new ArrayList<>();
seq.iterator().forEachRemaining(list::add);
Also, make sure that you absolutely need to return a Sequence in Kotlin's code. If you want to achieve better interoperability, returning a Stream would make more sense.
Like this:
val javaList = java.util.ArrayList<String>()
val kotlinSeq = javaList.asSequence()
val newJavaList = java.util.ArrayList<String>().apply { kotlinSeq.toCollection(this) }

How to convert a List[java.lang.Long] to a List[scala.Long]

I'm trying to convert from a java List to a scala List[scala.Long], i have seen from scala to java, but not the other way around.
I have tried using:
def convertJavaList2ScalaList[A]( list : java.util.List[A] ) : List[A]
={
val buffer = list.asScala
buffer.toList
}
And it works for other Objects (Eg. Person), but doesn't work when i try to convert scala.Long to java.lang.Long
Thanks for the help.
import scala.collection.JavaConverters._
// given a Java List of Java Longs:
val jlist: java.util.List[java.lang.Long] = ???
val scalaList: List[Long] = jlist.asScala.toList.map(_.toLong)

Convert Java ArrayList of objects to scala seq

I have ArrayList in Java which holds objects of type Row such as following
List<Row> Table = new ArrayList<Row>();
I need to convert this Table to Scala Seq in order to later convert it to data-frame. I tried the following without success
var TableScala:Seq[Row] =
Table.asScalaJavaConverters.asScalaBufferConverter(getTable).asScala
val newList = TableScala.map(row => new Tuple5(row(0), row(1), row(2), row(3), row(4)))
spark.createDataFrame(newList).toDF("userID")
From Scala 2.8.1, these conversions are made explicit using “scala.collection.JavaConverters._” api. The following code shows same conversion using this api.
First import
import scala.collection.JavaConverters._
Java list
List<Row> javaList = new ArrayList<Row>();
Use “asScala “ to convert Java list to Scala list
val scalaList = javaList.asScala
val squareList = scalaList.map(value => value*value)
println("square list is" + squareList)
reference : http://blog.madhukaraphatak.com/converting-java-collections-to-scala/

convert scala hashmap with List to java hashmap with java list

I am new to scala and spark.I have below case class A
case class A(uniqueId : String,
attributes: HashMap[String, List[String]])
Now I have a dataFrame of type A. I need to call a java function on each row of that DF. I need to convert Hashmap to Java HashMap and List to java list..
How can i do that.
I am trying to do following
val rddCaseClass = RDD[A]
val a = rddCaseClass.toDF().map ( x=> {
val rowData = x.getAs[java.util.HashMap[String,java.util.List[String]]]("attributes")
callJavaMethod(rowData)
But this is giving me error :
java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot be cast to java.util.List
Please help.
You can convert Scala Wrapped array to Java List using
scala.collection.JavaConversions
val wrappedArray: WrappedArray[String] = WrappedArray.make(Array("Java", "Scala"))
val javaList = JavaConversions.mutableSeqAsJavaList(wrappedArray)
JavaConversions.asJavaList can also be used but its deprecated: use mutableSeqAsJavaList instead
I think, you could use Seq instead of List for your parameters to work efficiently with List. This way it should work with most of the Seq implementations and no need to to convert the seqs like WrappedArray.
val rddCaseClass = RDD[A]
val a = rddCaseClass.toDF().map ( x=> {
val rowData = x.getAs[java.util.HashMap[String, Seq[String]]]("attributes")
callJavaMethod(rowData)

Scala equivalent of new HashSet(Collection)

What is the equivalent Scala constructor (to create an immutable HashSet) to the Java
new HashSet<T>(c)
where c is of type Collection<? extends T>?.
All I can find in the HashSet Object is apply.
The most concise way to do this is probably to use the ++ operator:
import scala.collection.immutable.HashSet
val list = List(1,2,3)
val set = HashSet() ++ list
There are two parts to the answer. The first part is that Scala variable argument methods that take a T* are a sugaring over methods taking Seq[T]. You tell Scala to treat a Seq[T] as a list of arguments instead of a single argument using "seq : _*".
The second part is converting a Collection[T] to a Seq[T]. There's no general built in way to do in Scala's standard libraries just yet, but one very easy (if not necessarily efficient) way to do it is by calling toArray. Here's a complete example.
scala> val lst : java.util.Collection[String] = new java.util.ArrayList
lst: java.util.Collection[String] = []
scala> lst add "hello"
res0: Boolean = true
scala> lst add "world"
res1: Boolean = true
scala> Set(lst.toArray : _*)
res2: scala.collection.immutable.Set[java.lang.Object] = Set(hello, world)
Note the scala.Predef.Set and scala.collection.immutable.HashSet are synonyms.
From Scala 2.13 use the companion object
import scala.collection.immutable.HashSet
val list = List(1,2,3)
val set = HashSet.from(list)

Categories