2010-01-06 12 views
12

Estaba tratando de extraer variables de entorno en un script de scala utilizando iteradores y/o enumeraciones de Java y me di cuenta de que el Dr. Frankenstein podría reclamar el parentesco, así que pirateé el siguiente del feo árbol:Obteniendo un mapa de Scala desde las propiedades de Java

import java.util.Map.Entry 
import System._ 

val propSet = getProperties().entrySet().toArray() 
val props = (0 until propSet.size).foldLeft(Map[String, String]()){(m, i) => 
    val e = propSet(i).asInstanceOf[Entry[String, String]] 
    m + (e.getKey() -> e.getValue()) 
} 

por ejemplo, para imprimir el dicho mismo entorno

props.keySet.toList.sortWith(_ < _).foreach{k => 
    println(k+(" " * (30 - k.length))+" = "+props(k)) 
} 

por favor, por favor no se dedicó a pulir este t $ # d, me acaba de mostrar la gema Scala que estoy convencido de que existe para este situación (es decir, propiedades de Java -> scala.Map), gracias de antemano; @)

+1

Scala gem, eh? Rubyist? –

+0

No, Ruby es demasiado genial para mí, supongo que fue la copia de C++ Gems de Stan Lippman en el estante lo que me llamó la atención. –

Respuesta

7

Scala 2.7:

val props = Map() ++ scala.collection.jcl.Conversions.convertMap(System.getProperties).elements 

A pesar de que necesita un poco de encasillamiento. Déjame trabajar un poco más.

val props = Map() ++ scala.collection.jcl.Conversions.convertMap(System.getProperties).elements.asInstanceOf[Iterator[(String, String)]] 

Ok, eso fue fácil. Déjame trabajar en 2.8 ahora ...

import scala.collection.JavaConversions.asMap 
val props = System.getProperties() : scala.collection.mutable.Map[AnyRef, AnyRef] // or 
val props = System.getProperties().asInstanceOf[java.util.Map[String, String]] : scala.collection.mutable.Map[String, String] // way too many repetitions of types 
val props = asMap(System.getProperties().asInstanceOf[java.util.Map[String, String]]) 

La verbosidad, por supuesto, se puede disminuir con un par de importaciones. En primer lugar, tenga en cuenta que Map será un mapa mutable en 2.8. En el lado positivo, si convierte de nuevo el mapa, obtendrá el objeto original.

Ahora, no tengo ni idea de por qué Properties implementa Map<Object, Object>, dado que los javadocs indican claramente que la clave y el valor son String, pero ya está. Tener que encasillar esto hace que la opción implícita sea mucho menos atractiva. Siendo este el caso, la alternativa es la más concisa de ellas.

EDITAR

Scala 2,8 acaba de adquirir una conversión implícita Properties-mutable.Map[String,String], lo que hace que la mayor parte de ese código discutible.

+0

Como nota al margen, esta es la primera vez que hago Java <-> conversiones de la colección Scala. La última vez que lo intenté no tuve la experiencia suficiente para hacerlo funcionar. Y no solo tuve la oportunidad de superar mi derrota anterior, sino que encontré este problema particular de mucho interés, ¡ya que de vez en cuando me encuentro leyendo las propiedades del sistema! –

+0

Gracias Daniel, le daré una respuesta adecuada después. Me complace haber despertado su interés en este tema. –

+0

@Daniel, sospecho que esta es la gema que estaba buscando, solo una pena por el yeso, especialmente porque las propiedades deberían implementar Map [String, String]. Estas conversiones son un gran hallazgo para mí. –

4

En Scala 2.8.1 se puede hacer con asScalaMap(m : java.util.Map[A, B]) de una manera más concisa:

var props = asScalaMap(System.getProperties()) 

props.keySet.toList.sortWith(_ < _).foreach { k => 
    println(k + (" " * (30 - k.length)) + " = " + props(k)) 
} 
+0

Gracias Vitalii, eché un vistazo a ascalamap y también hay una versión de asScalaMap que permite una conversión implícita de una instancia de propiedades java a un mapa mutable de Scala [String, Cuerda]. –

7

En Scala 2.9.1 esto se resuelve mediante las conversiones implícitas dentro collection.JavaConversions._. Las otras respuestas usan funciones obsoletas. Los detalles están documentados here. Este es un fragmento relevante de esa página:

scala> import collection.JavaConversions._ 
import collection.JavaConversions._ 

scala> import collection.mutable._ 
import collection.mutable._ 
scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3) 
jul: java.util.List[Int] = [1, 2, 3] 
scala> val buf: Seq[Int] = jul 
buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3) 
scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2) 
m: java.util.Map[String,Int] = {hello=2, abc=1} 

¿Cómo salir de un mapa mutable a un mapa inmutable es una cuestión de llamar tomap en él.

+0

Gracias por la actualización, Daniel proporcionó una edición de su respuesta mencionando estos implicits. Irónicamente, el acceso al entorno será aún más sencillo en Scala 2.10, solo use el mapa inmutable devuelto por el método sys.env. –

+2

Me acabo de dar cuenta de que era una conversión de propiedades a un mapa de Scala que había solicitado, sin embargo Scala 2.10 también tiene un método sys.props para acceder a las propiedades del sistema también. –

+1

La edición en la respuesta de Daniels es sobre Scala 2.8, y ha cambiado nuevamente en 2.9 ... Sé que es confuso. – iwein

1

Parece que en la versión más reciente de la Scala (2.10.2 como parte del tiempo de esta respuesta), la mejor forma de hacerlo es usando la explícita .asScala de scala.collection.JavaConverters:

import scala.collection.JavaConverters._ 

val props = System.getProperties().asScala 

assert(props.isInstanceOf[Map[String, String]]) 
+0

Esta es la mejor respuesta IMO. Gracias. – Jabba

4

Scala 2.10. 3

import scala.collection.JavaConverters._ 

//Create a variable to store the properties in 
val props = new Properties 

//Open a file stream to read the file 
val fileStream = new FileInputStream(new File(fileName)) 
props.load(fileStream) 
fileStream.close() 

//Print the contents of the properties file as a map 
println(props.asScala.toMap) 
+0

Hola Sarath. Gracias por contribuir al sitio. Preferimos que las respuestas en StackOverflow tengan un poco más de explicación que simplemente publicar el código. Intente leer esta [guía para publicar buenas respuestas] (http://stackoverflow.com/help/how-to-answer) para obtener más ayuda :) – starsplusplus

Cuestiones relacionadas