Utilities for seamless conversion between Scala and Java collections. Provides both implicit extension methods for Scala code and explicit conversion methods for Java interoperability.
Extension methods that add .asScala and .asJava to collections for convenient conversion in Scala code.
import scala.jdk.CollectionConverters._
// Extension methods available on Java collections
implicit class IteratorHasAsScala[A](i: ju.Iterator[A]) {
def asScala: Iterator[A]
}
implicit class EnumerationHasAsScala[A](e: ju.Enumeration[A]) {
def asScala: Iterator[A]
}
implicit class IterableHasAsScala[A](i: jl.Iterable[A]) {
def asScala: Iterable[A]
}
implicit class CollectionHasAsScala[A](c: ju.Collection[A]) {
def asScala: Iterable[A]
}
implicit class ListHasAsScala[A](l: ju.List[A]) {
def asScala: mutable.Buffer[A]
}
implicit class SetHasAsScala[A](s: ju.Set[A]) {
def asScala: mutable.Set[A]
}
implicit class MapHasAsScala[K, V](m: ju.Map[K, V]) {
def asScala: mutable.Map[K, V]
}
implicit class ConcurrentMapHasAsScala[K, V](m: juc.ConcurrentMap[K, V]) {
def asScala: concurrent.Map[K, V]
}
implicit class DictionaryHasAsScala[K, V](d: ju.Dictionary[K, V]) {
def asScala: mutable.Map[K, V]
}
implicit class PropertiesHasAsScala(p: ju.Properties) {
def asScala: mutable.Map[String, String]
}
// Extension methods available on Scala collections
implicit class IteratorHasAsJava[A](i: Iterator[A]) {
def asJava: ju.Iterator[A]
}
implicit class IterableHasAsJava[A](i: Iterable[A]) {
def asJava: jl.Iterable[A]
}
implicit class BufferHasAsJava[A](b: mutable.Buffer[A]) {
def asJava: ju.List[A]
}
implicit class MutableSeqHasAsJava[A](s: mutable.Seq[A]) {
def asJava: ju.List[A]
}
implicit class SeqHasAsJava[A](s: Seq[A]) {
def asJava: ju.List[A]
}
implicit class MutableSetHasAsJava[A](s: mutable.Set[A]) {
def asJava: ju.Set[A]
}
implicit class SetHasAsJava[A](s: Set[A]) {
def asJava: ju.Set[A]
}
implicit class MutableMapHasAsJava[K, V](m: mutable.Map[K, V]) {
def asJava: ju.Map[K, V]
}
implicit class MapHasAsJava[K, V](m: Map[K, V]) {
def asJava: ju.Map[K, V]
}
implicit class ConcurrentMapHasAsJava[K, V](m: concurrent.Map[K, V]) {
def asJava: juc.ConcurrentMap[K, V]
}Usage Examples:
import scala.jdk.CollectionConverters._
import java.util.{ArrayList, HashMap, HashSet}
import scala.collection.mutable
// Java to Scala conversion
val javaList = new ArrayList[String]()
javaList.add("hello")
javaList.add("world")
val scalaBuffer = javaList.asScala // mutable.Buffer[String]
val javaMap = new HashMap[String, Int]()
javaMap.put("one", 1)
javaMap.put("two", 2)
val scalaMap = javaMap.asScala // mutable.Map[String, Int]
// Scala to Java conversion
val scalaList = List("a", "b", "c")
val javaListFromScala = scalaList.asJava // java.util.List[String]
val scalaSet = Set(1, 2, 3)
val javaSetFromScala = scalaSet.asJava // java.util.Set[Int]
// Chaining conversions in data processing
def processWithJavaLibrary(data: List[String]): List[String] = {
val javaResult = someJavaLibrary.process(data.asJava)
javaResult.asScala.toList
}Explicit conversion methods designed for use from Java code or when implicit conversions are not desired.
import scala.jdk.javaapi.CollectionConverters
// Java to Scala conversions
object CollectionConverters {
/**
* Convert Java Iterator to Scala Iterator
* @param i Java Iterator
* @return Scala Iterator
*/
def asScala[A](i: ju.Iterator[A]): Iterator[A]
/**
* Convert Java Enumeration to Scala Iterator
* @param e Java Enumeration
* @return Scala Iterator
*/
def asScala[A](e: ju.Enumeration[A]): Iterator[A]
/**
* Convert Java Iterable to Scala Iterable
* @param i Java Iterable
* @return Scala Iterable
*/
def asScala[A](i: jl.Iterable[A]): Iterable[A]
/**
* Convert Java Collection to Scala Iterable
* @param c Java Collection
* @return Scala Iterable
*/
def asScala[A](c: ju.Collection[A]): Iterable[A]
/**
* Convert Java List to Scala mutable Buffer
* @param l Java List
* @return Scala mutable Buffer
*/
def asScala[A](l: ju.List[A]): mutable.Buffer[A]
/**
* Convert Java Set to Scala mutable Set
* @param s Java Set
* @return Scala mutable Set
*/
def asScala[A](s: ju.Set[A]): mutable.Set[A]
/**
* Convert Java Map to Scala mutable Map
* @param m Java Map
* @return Scala mutable Map
*/
def asScala[A, B](m: ju.Map[A, B]): mutable.Map[A, B]
/**
* Convert Java ConcurrentMap to Scala concurrent Map
* @param m Java ConcurrentMap
* @return Scala concurrent Map
*/
def asScala[A, B](m: juc.ConcurrentMap[A, B]): concurrent.Map[A, B]
/**
* Convert Java Dictionary to Scala mutable Map
* @param d Java Dictionary
* @return Scala mutable Map
*/
def asScala[A, B](d: ju.Dictionary[A, B]): mutable.Map[A, B]
/**
* Convert Java Properties to Scala mutable Map
* @param p Java Properties
* @return Scala mutable Map[String, String]
*/
def asScala(p: ju.Properties): mutable.Map[String, String]
// Scala to Java conversions
/**
* Convert Scala Iterator to Java Iterator
* @param i Scala Iterator
* @return Java Iterator
*/
def asJava[A](i: Iterator[A]): ju.Iterator[A]
/**
* Convert Scala Iterable to Java Iterable
* @param i Scala Iterable
* @return Java Iterable
*/
def asJava[A](i: Iterable[A]): jl.Iterable[A]
/**
* Convert Scala mutable Buffer to Java List
* @param b Scala Buffer
* @return Java List
*/
def asJava[A](b: mutable.Buffer[A]): ju.List[A]
/**
* Convert Scala mutable Seq to Java List
* @param s Scala mutable Seq
* @return Java List
*/
def asJava[A](s: mutable.Seq[A]): ju.List[A]
/**
* Convert Scala Seq to Java List
* @param s Scala Seq
* @return Java List
*/
def asJava[A](s: Seq[A]): ju.List[A]
/**
* Convert Scala mutable Set to Java Set
* @param s Scala mutable Set
* @return Java Set
*/
def asJava[A](s: mutable.Set[A]): ju.Set[A]
/**
* Convert Scala Set to Java Set
* @param s Scala Set
* @return Java Set
*/
def asJava[A](s: Set[A]): ju.Set[A]
/**
* Convert Scala mutable Map to Java Map
* @param m Scala mutable Map
* @return Java Map
*/
def asJava[K, V](m: mutable.Map[K, V]): ju.Map[K, V]
/**
* Convert Scala Map to Java Map
* @param m Scala Map
* @return Java Map
*/
def asJava[K, V](m: Map[K, V]): ju.Map[K, V]
/**
* Convert Scala concurrent Map to Java ConcurrentMap
* @param m Scala concurrent Map
* @return Java ConcurrentMap
*/
def asJava[K, V](m: concurrent.Map[K, V]): juc.ConcurrentMap[K, V]
}Usage Examples:
import scala.jdk.javaapi.CollectionConverters
import java.util.{ArrayList, HashMap}
// Explicit conversions (useful in Java interop scenarios)
val javaList = new ArrayList[String]()
val scalaBuffer = CollectionConverters.asScala(javaList)
val scalaList = List("a", "b", "c")
val javaListExplicit = CollectionConverters.asJava(scalaList)
// In Java code, these methods are easily accessible:
// scala.jdk.javaapi.CollectionConverters.asJava(scalaCollection)Working with Java Libraries:
import scala.jdk.CollectionConverters._
import java.util.concurrent.ConcurrentHashMap
class ScalaServiceWithJavaCache {
private val javaCache = new ConcurrentHashMap[String, String]()
def put(key: String, value: String): Unit = {
javaCache.put(key, value)
}
def getAll: Map[String, String] = {
javaCache.asScala.toMap // Convert to immutable Scala Map
}
def processKeys(processor: String => String): Unit = {
javaCache.asScala.keys.foreach { key =>
val newValue = processor(key)
javaCache.put(key, newValue)
}
}
}Streaming and Processing:
import scala.jdk.CollectionConverters._
import java.util.stream.Collectors
def processJavaStream[T](javaList: ju.List[T],
filter: T => Boolean,
transform: T => String): List[String] = {
javaList.stream()
.filter(filter(_))
.map(transform(_))
.collect(Collectors.toList())
.asScala
.toList
}
// Alternative using Scala collections
def processWithScalaCollections[T](javaList: ju.List[T],
filter: T => Boolean,
transform: T => String): List[String] = {
javaList.asScala
.filter(filter)
.map(transform)
.toList
}Configuration and Properties:
import scala.jdk.CollectionConverters._
import java.util.Properties
class ConfigurationManager {
private val props = new Properties()
def loadFromJavaProperties(javaProps: Properties): Unit = {
// Convert to Scala Map for easier processing
val scalaConfig = javaProps.asScala
scalaConfig.foreach { case (key, value) =>
val processedValue = processConfigValue(key, value)
props.setProperty(key, processedValue)
}
}
def getConfigAsScalaMap: Map[String, String] = {
props.asScala.toMap
}
private def processConfigValue(key: String, value: String): String = {
// Process configuration values using Scala string methods
value.trim.toLowerCase
}
}Integration with Java Frameworks:
import scala.jdk.CollectionConverters._
// Example: Working with Java collection-based APIs
class DatabaseService {
def findUsersByIds(userIds: Set[Long]): List[User] = {
// Java database library expects java.util.Set
val javaUserIds = userIds.asJava
val javaResults = databaseLibrary.findByIds(javaUserIds)
// Convert results back to Scala collections
javaResults.asScala.toList
}
def saveUsers(users: List[User]): Boolean = {
val javaUsers = users.asJava
databaseLibrary.saveAll(javaUsers)
}
}View-Based Conversions:
The conversion methods create views rather than copying data, making them efficient for large collections:
import scala.jdk.CollectionConverters._
val largeScalaList = (1 to 1000000).toList
val javaView = largeScalaList.asJava // No copying, creates a view
// Modifications to the original affect the view
val mutableBuffer = scala.collection.mutable.Buffer(1, 2, 3)
val javaList = mutableBuffer.asJava
mutableBuffer += 4
// javaList now also contains 4Bulk Operations:
For operations that need to process entire collections, consider converting once rather than per-element:
import scala.jdk.CollectionConverters._
// Efficient: Convert once
def processEfficiently(javaList: ju.List[String]): List[String] = {
javaList.asScala
.filter(_.nonEmpty)
.map(_.toUpperCase)
.toList
}
// Less efficient: Multiple conversions
def processInefficiently(javaList: ju.List[String]): ju.List[String] = {
javaList.asScala
.filter(_.nonEmpty)
.map(_.toUpperCase)
.asJava
}