常见问题
根据类的不同属性进行排序-1
需要对类的集合按照不同的字段进行排序,排序的规则可以指定:
case class Item(good:String, bad:String, gross:Int, warn:String)
trait BaseSort{
def sort[A, B: Ordering](data: List[A], desc: Boolean)(measure: A => B): List[A] = {
val baseOrdering = Ordering.by(measure)
val ordering = if (desc) baseOrdering.reverse else baseOrdering
data.sorted(ordering)
}
}
trait ItemsSort extends BaseSort{
def sortItems(items:List[Item], by:String, desc:Boolean): List[Item] = by match {
case "good" => sort(items, desc=desc)(_.good)
case "bad" => sort(items, desc=desc)(_.bad)
case "gross" => sort(items, desc=desc)(_.gross)
case "warn" => sort(items, desc=desc)(_.warn)
case _ => items
}
}
val items:List[Item] = List(Item("a","a",1,"a"),Item("b","b",2,"b"),Item("c","c",3,"c"))
sortItems(items, "good",desc = true).foreach(println)
根据类的不同属性进行排序-2
另一种方式是首先预定义需要的排序规则,然后在需要的位置做为隐式参数引入:
case class Item2(id:Int, firstName:String, lastName:String)
object Item2{
// 注意,因为`Ordering[A]`不是逆变的,如果`Item`的子类想要使用该排序方式,则必须声明为参数化类型
implicit def orderByName[A <: Item2]: Ordering[A] =
Ordering.by(e => (e.firstName,e.lastName))
val orderingById: Ordering[Item2] = Ordering.by(_.id)
}
object CustomClassSort2 extends App{
val items:List[Item2] = List(Item2(2,"ccc","ddd"),Item2(1,"aaa","bbb"))
import Item2.orderByName // 直接引入隐式参数
items.sorted.foreach(println)
implicit val ording = Item2.orderingById // 引入排序规则后定义为隐式参数
items.sorted.foreach(println)
}
隐式转换
将类自动转换为元组
有时候需要将一些case class
自动转换为元组以方便处理:
case class Foo(a:String, b:String)
implicit def asTuple(foo:Foo):(String,String) = Foo.unapply(foo).get
val foo1 = Foo("aa","bb")
val (a:String,b:String):(String,String) = foo1
不可过度使用元组
对元组过度的使用会使代码难于理解,特别是元素特别多的元组,比如:
def bestByName(query:String, actors:List[(Int, String, Double)]) =
actors.filter { _._2 contains query}
.sortBy { _._3}
.map { _._1}
.take(10)
而是应该讲使用频繁的元组作为一个case class
,并且将各阶段的中间处理过程进行易于理解的命名:
case class Actor(id:Int, name:String, score:Double)
def bestByName(query:String, actors:List[Actor]) = {
val candidates = actors.filter{ _.name contains query}
val ranked = canditates.sortBy { _.score }
val best = ranked take 10
best map { _.id }
}
可变数据类型的选择
在一个函数或者私有类中时,如果一个可变的数据类型能够有效的缩减代码,这时就可以使用可变数据类型,比如var
或者colleciton.mutable
,因为没有外部的动作可以对他们造成改变。
函数重复参数传入
比如定义一个方法:
def echo(args:String*) = args.forearh(println)
该函数能够接受一个或多个 String 类型的参数,比如:
echo("aa")
echo("bb","cc")
这个String*
实际上是一个Array[String]
,但是当传入一个已存在的序列时,需要先将其展开:
val seq:Seq[String] = Seq("aa","bb","cc")
echo(seq:_*)
这个标注告诉编译器将序列的每个元素当做一个参数,而不是将整个序列做为一个单一的参数传入。直接传入序列将会报错。
并行集合
为并行集合指定线程数
Configuring Parallel Collections
scala> import scala.collection.parallel._
scala> val pc = mutable.ParArray(1, 2, 3)
scala> pc.tasksupport = new ForkJoinTaskSupport(newscala.concurrent.forkjoin.ForkJoinPool(2))
scala> pc map { _ + 1 }
res0: scala.collection.parallel.mutable.ParArray[Int] = ParArray(2, 3, 4)
异常
NoSuchMethodError
此类异常多为使用了错误版本的 JDK 或 Scala。
获取代码运行时间
val t1 = System.nanoTime
/* your code */
val duration = (System.nanoTime - t1) / 1e9d
为Future添加一个基于时间的监控器
import scala.concurrent.duration._
import java.util.concurrent.{Executors, ScheduledThreadPoolExecutor}
import scala.concurrent.{Future, Promise}
val f: Future[Int] = ???
val executor = new ScheduledThreadPoolExecutor(2, Executors.defaultThreadFactory(), AbortPolicy)
def withDelay[T](operation: ⇒ T)(by: FiniteDuration): Future[T] = {
val promise = Promise[T]()
executor.schedule(new Runnable {
override def run() = {
promise.complete(Try(operation))
}
}, by.length, by.unit)
promise.future
}
Future.firstCompletedOf(Seq(f, withDelay(println("still going"))(30 seconds)))
Future.firstCompletedOf(Seq(f, withDelay(println("still still going"))(60 seconds)))
logback 避免日志重复
<logger name="data-logger" level="info" additivity="false">
Loggers are hierarchical, and any message sent to a logger will be sent to all its ancestors by default. You can disable this behavior by setting additivity=false.
OkHttp异步请求
BUG:大量请求之后资源耗尽导致服务不可用,虽然已经关闭了response
。
import java.util.concurrent.TimeUnit
import okhttp3._
trait OkHttpBuilder {
val httpClient: OkHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(45, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.followSslRedirects(true)
.followRedirects(true)
.build()
def cloneHttpClient() = httpClient.newBuilder().build()
}
object OkHttpBuilder extends OkHttpBuilder
private def asyncDownload(src: String, superior: ActorRef) = {
try {
val client: OkHttpClient = OkHttpBuilder.cloneHttpClient()
val request = new Request.Builder().url(src).get().addHeader("User-Agent", web).build()
client.newCall(request).enqueue(new Callback {
override def onFailure(call: Call, e: IOException): Unit = {
logger.error(s"ImageProcessor.DownloadErr - 1: $src, ${e.getMessage}")
superior ! Redownload(src)
}
override def onResponse(call: Call, response: Response): Unit = {
response.isSuccessful match {
case false =>
logger.error(s"ImageProcessor.DownloadErr - 2: $src, ${response.code()}")
superior ! Discard(src)
response.close()
case true => try {
val stream: InputStream = response.body().byteStream()
val bytes: Array[Byte] = IOUtils.toByteArray(stream)
save(src, bytes) match {
case Some(path) =>
upload(path) match {
case Some(pathU) => superior ! Oss(src, pathU)
case None => superior ! Redownload(src)
}
case None => superior ! Discard(src)
}
} catch {
case NonFatal(e) =>
logger.error(s"ImageProcessor.DownloadErr - 3: $src, ${e.getMessage}")
superior ! Redownload(src)
} finally {
response.close()
}
}
}
})
} catch {
case ex: IOException =>
logger.error(s"ImageProcessor.DownloadErr- IOException: $src, ${ex.getMessage}")
superior ! Redownload(src)
case NonFatal(e) =>
logger.error(s"ImageProcessor.DownloadErr - 0: $src, ${e.getMessage}")
superior ! Redownload(src)
}
}
获取系统包路径
java -XshowSettings:properties -version // java 8
或:
public class PrintLibPath{
public static void main(String[] args){
System.out.println(System.getProperty("java.library.path"));
}
}
javac PrintLibPath.java
java -cp /path PrintLibPath
/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib # centos 6.5
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.