Using this class I'm attempting to modify the String parameter of the constructor and convert it to date :
class OrderInstance(var size: Double,
var side: String,
var trade_id: Int,
var price: Double,
var time: java.util.Date,
var code: String) {
def getTime(time: String): java.util.Date = new java.util.Date()
def this(size: String,
side: String,
trade_id: Int,
price: String,
time: String, code: String) = this(size.toDouble: Double,
side: String,
trade_id: Int,
price.toDouble: Double,
getTime(time: String) : java.util.Date, code: String)
// Step 3 - proper signature for `equals`
// Steps 4 thru 7 - implement a `match` expression
override def equals(that: Any): Boolean =
that match {
case that: OrderInstance => {
that.canEqual(this) &&
this.trade_id == that.trade_id
}
case _ => false
}
// Step 1 - proper signature for `canEqual`
// Step 2 - compare `a` to the current class
def canEqual(a: Any) = a.isInstanceOf[OrderInstance]
// Step 8 - implement a corresponding hashCode c=method
override def hashCode: Int = {
val prime = 31
var result = 1
result = prime * result + trade_id;
result = prime * result + (if (code == null) 0 else code.hashCode)
result
}
override def toString = {
String.valueOf(trade_id)
}
}
This line :
def getTime(time: String): java.util.Date = new java.util.Date()
should be called in order to return a date instead of String. But I receive error :
Error:(54, 7) not found: value getTime
getTime(time: String) : java.util.Date, code: String)
This error is reported at run time, not compile time. Have I not defined the function getTime correctly ?
Update :
I've attempted to make more clear what I'm trying to achieve :
class OrderInstance(var size: Double,
var side: String,
var trade_id: Int,
var price: Double,
var time: String,
var code: String){
this(time) = this(OrderInstance.getTime(time))
def this(size: String,
side: String,
trade_id: Int,
price: String,
time: String, code: String) = this(size.toDouble: Double,
side: String,
trade_id: Int,
price.toDouble: Double,
time : String, code: String)
// Step 3 - proper signature for `equals`
// Steps 4 thru 7 - implement a `match` expression
override def equals(that: Any): Boolean =
that match {
case that: OrderInstance => {
that.canEqual(this) &&
this.trade_id == that.trade_id
}
case _ => false
}
// Step 1 - proper signature for `canEqual`
// Step 2 - compare `a` to the current class
def canEqual(a: Any) = a.isInstanceOf[OrderInstance]
// Step 8 - implement a corresponding hashCode c=method
override def hashCode: Int = {
val prime = 31
var result = 1
result = prime * result + trade_id;
result = prime * result + (if (code == null) 0 else code.hashCode)
result
}
override def toString = {
String.valueOf(trade_id)
}
}
object OrderInstance {
def getTime(time: String): java.util.Date = new java.util.Date()
}
new OrderInstance(1.0 , "" , 1 , 1.0 , "2019-09-13T16:27:19.881Z" , "")
This returns error :
Error:(60, 26) OrderInstance does not take parameters
this(time) = this(OrderInstance.getTime(time))
for line
this(time) = this(OrderInstance.getTime(time))
How to update time to be converted to Date instead of String ?
getTime is an instance method, which you're trying to invoke from a constructor, i.e. before the instance has been created. Since getTime doesn't actually use any instance variables, you'll want to place it in a companion object (the scala equivalent of static)
class OrderInstance(
//...
) {
this(string) = this(OrderInstance.getTime(string))
}
object OrderInstance {
def getTime(time: String): java.util.Date = new java.util.Date()
}
Thanks to answer from user user1186491 this works as expected :
class OrderInstance(var time: java.util.Date){
def this(time: String) = this(
OrderInstance.getTime(time))
}
object OrderInstance {
def getTime(time: String): java.util.Date = new java.util.Date()
}
val o = new OrderInstance("2019-09-13T16:27:19.881Z" )
println(o.time)
Related
I am trying to create a generic code to read using spark sql from a view. Where T can be any object passed at runtime, I should be able to get DataSet of T.
Method
def queryStream[T](sparkSession: SparkSession, query: String, filterParams: Array[String])(implicit tag: ClassTag[T]): Dataset[T] = sparkSession.sql(query)
.as(Encoders.bean[KafkaMessage](classOf[KafkaMessage]))
.map(f => {
init()
getObjectMapper.readValue(f.message, classTag[T].runtimeClass).asInstanceOf[T]
})(Encoders.bean[T](classOf[T]))
Invocation :
queryStream[Student](sparkSession,"select cast(value as string) as message,"
+ "cast(key as string) as messageKey, " +
"cast(partition as int) partition, " +
"cast(offset as long) offset from events",null)
KafkaMessage:
class KafkaMessage {
#BeanProperty
var messageKey: String = _
#BeanProperty
var message: String = _
#BeanProperty
var partition: Int = _
#BeanProperty
var offset: Long = _
override def toString(): String = s"Message Key: $messageKey, Message: $message, Partition:$partition, Offset:$offset"
}
case class ACase( name: String)
case class BCase( name: String, num: Int)
I have ACase's dataset and would like to change it as BCase type with adding column. Here is my try.
def makeBCase( aCase: ACase, num: Int) : BCase = {
BCase( aCase.name, num)
}
def change( aDS: Dataset[ACase]): Dataset[BCase] = {
val bDS = aDS.map { a =>
makeBCase( a, 123)
}
....
bDS // error - type mismatch; required : org.apache.spark.sql.Dataset[ACase]
}
How can I change Its type?
I have the following enum.
object Smth extends Enumeration {
class Value(name: String, func: (String, Int) => Boolean) extends super.Val(name)
private def opA(index: Int) : Boolean ={
index > 0
}
private def opB(x: String, index: Int) : Boolean ={
index > 0 && x.length > 0
}
val x = new Value("X", opA) // type mismatch error for opA
val y = new Value("Y", opB)
}
Enum constructor takes as an argument a function, of type (String, Int) => Boolean. Is it possible to create enum constructor in such a way that it will accept functions with 2 distinct contracts, for example:
(String, Int) => Boolean
(Int) => Boolean
I am trying to avoid using default value for argument, in function definition.
This is how I would like to use it.
if(Smth.x.func(0)) { do smth }
else if(Smth.y.func("str", 0)) { do smthElse }
If you just want default value you can do this:
class Value(val name: String, val func: (String, Int) => Boolean) extends super.Val(name) {
def apply(name: String, func: (Int) => Boolean): Value =
new Value(name, (x -> func("default value", x)))
}
I'm trying to create a custom data type that behaves like an Int, but has certain specific behavior and typing (eg., it has to be positive, it has to fit within the range of our database's 'integer' type, etc).
To make it a friendly class, I want to have custom assignment operators, etc., for instance I'd like the following to all work:
val g: GPID = 1 // create a GPID type with value 1
val g: GPID = 1L // take assignment from a Long (and downcast into Int)
if (g == 1) ... // test the value of GPID type against an Int(1)
This is what I have so far but I'm not getting the expected behavior:
case class GPID(value: Int) extends MappedTo[Int] {
require(value >= 1, "GPID must be a positive number")
require(value <= GPDataTypes.integer._2, s"GPID upper bound is ${GPDataTypes.integer._2}")
def this(l: Long) = this(l.toInt)
def GPID = value
def GPID_=(i: Int) = new GPID(i)
def GPID_=(l: Long) = new GPID(l.toInt)
override def toString: String = value.toString
override def hashCode:Int = value
override def equals(that: Any): Boolean =
that match {
case that: Int => this.hashCode == that.hashCode
case that: Long => this.hashCode == that.hashCode
case _ => false
}
}
object GPID {
implicit val writesGPID = new Writes[GPID] {
def writes(g: GPID): JsValue = {
Json.obj(
"GPID" -> g.value
)
}
}
implicit val reads: Reads[GPID] = (
(__ \ "GPID").read[GPID]
)
def apply(l: Long) = new GPID(l.toInt)
implicit def gpid2int(g: GPID): Int = hashCode
implicit def gpid2long(g: GPID): Long = hashCode.toLong
}
The problems I have are:
Assignment doesn't work, for instance:
val g: GPID = 1
Implicit conversion is not working, for instance:
val i: Int = g
Any help would be appreciated... haven't build a custom type like this before so overriding assignment and implicit conversion is new to me...
object TestInt extends App {
class GPID(val value: Int) {
require(value >= 1, "GPID must be a positive number")
require(value <= 10, s"GPID upper bound is 10")
override def equals(that: Any) = value.equals(that)
override def toString = value.toString
// add more methods here (pimp my library)
}
implicit def fromInt(value: Int) = new GPID(value)
implicit def fromInt(value: Long) = new GPID(value.toInt) //possible loss of precision
val g: GPID = 1
val g2: GPID = 1L
if (g == 1)
println("ONE: " + g)
else
println("NOT ONE: " + g)
}
Prints:
ONE: 1
I have big object:
case class BigObject(val str: String, val number: Int) {
val someVal = ...
val someVal2 = ...
}
I'd like to copy this object without re-valuation of values. Is it possible? Right now I'm using this approach:
val newBigObject = oldBigObject.copy(str = newStr)
As I see from the logs/debugger, "someVal" and "someVal2" are re-valuated. Is it possible to avoid it? As my BigObject is really big and value re-valuation takes some time, but performance is really important for me.
Thanks for your answers!
Here's a way:
Make the someVal and someVal2 fields which are also passed to the constructor and pull out the initialization logic for those fields in the companion object.
In your case:
class BigObject private(val str: String,
val number: Int,
val someVal: SomeType,
val someVal2: SomeType) {
def copy(newStr: String = str, newNumber: Int = number) = {
new BigObject(newStr, newNumber, someVal, someVal2)
}
}
object BigObject {
def apply(str: String, number: Int): BigObject = {
val someVal = initialize() //your initialization logic here
val someVal2 = initialize2()
new BigObject(str, number, someVal, someVal2)
}
}
Now, you can copy without re-evaling the inner fields:
val bigObj = BigObject("hello", 42)
val anotherBigObj = bigObj.copy(newStr = "anotherStr")
Alternatively, if you don't like companion objects, you can make two constructors. The primary one includes all the fields (also the non visible ones) and will be private. The public one will have only the two visible parameters:
class BigObject private(val str: String,
val number: Int,
val someVal: Any,
val someVal2: Any) {
def this(str: String, number: Int) = this(str, number, initializeVal, initializeVal2)
def copy(newStr: String = str, newNumber: Int = number) = {
new BigObject(newStr, newNumber, someVal, someVal2)
}
}
Usage:
val bigObj = new BigObject("hello", 42)
val anotherBigObj = bigObj.copy(newStr = "anotherStr")