Scala For Java的一些参考
变量String yourPast = "Good Java Programmer";
val yourPast : String = "Good Java Programmer"
val yourPast = "Good Java Programmer"
var yourFuture = "Good Java Programmer"
自动类型推断;可变、不可变变量
class Money(amount:Int) amount不是成员变量
class Money(val amount:Int)
val notMuch = new Money(2)
notMuch.amount
class Money(var amount:Int)
val notMuch = new Money(2)
notMuch.amount=3
case classes
public class Money {
private Integer amount;
private String currency;
public Money(Integer amount, String currency) {
this.amount = amount;
this.currency = currency;
}
public Integer getAmount() {
return amount;
}
public void setAmount(Integer amount) {
this.amount = amount;
}
public String getCurrency() {
return currency;
}
public voidsetCurrency(String currency) {
this.currency = currency;
}
@Override
public int hashCode() {
int hash = 5;
hash = 29 * hash + (this.amount != null ? this.amount.
hashCode() : 0);
hash = 29 * hash + (this.currency != null ? this.currency.
hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Money other = (Money) obj;
return true;
}
@Override
public String toString() {
return "Money{" + "amount=" + amount + ", currency=" +
currency + '}';
}
public Money add(Money other) {
return new Money(this.amount +
other.amount, this.currency);
}
}
case class Money(amount:Int=1, currency:String="USD")two immutable fields the fields declared in Scala classes are public
case class Money(private val amount: Int, private val currency: String)
to make them private instead, or usedvar instead ofval to make the fields mutable.
val defaultAmount = Money()
val fifteenDollars = Money(15,"USD")
val fifteenDollars = Money(15)
val someEuros = Money(currency="EUR")
case class Money(val amount:Int=1, val currency:String="USD"){
def +(other: Money) : Money = Money(amount + other.amount)
}
Money(12) + Money(34)
collections
Scala collections are, by default, immutable
val numbers = List(1,2,3,4,5,6)
val reversedList = numbers.reverse
val onlyAFew = numbers drop 2 take 3
cons operator
val numbers = 1 :: 2 :: 3 :: 4 :: 5 :: 6 :: Nil
val simpleList = Nil.::(6)
val twoElementsList = List(6).::(5)
列表串接
val concatenatedList = simpleList ::: twoElementsList
val things = List(0,1,true) AnyVal
val things = List(0,1,true,"false") Any
复杂对象列表
val amounts = List(Money(10,"USD"),Money(2,"EUR"),Money(20,"GBP"),
Money(75,"EUR"),Money(100,"USD"),Money(50,"USD"))
Filter
val euros = amounts.filter(money => money.currency=="EUR")
val euros = amounts.filter(x => x.currency=="EUR")
val euros = amounts.filter(_.currency=="EUR")
partition
val allAmounts = amounts.partition(amt => amt.currency=="EUR")
Tuples
val euros = allAmounts._1
val everythingButEuros= allAmounts._2
val (euros,everythingButEuros) = amounts.partition(amt => amt.currency=="EUR")
Map
Map amounts = new HashMap<String,Integer>();
amounts.put("USD", 10);
amounts.put("EUR", 2);
val wallet = Map( "USD" -> 10, "EUR" -> 2 )
val someEuros = wallet("EUR")
Option类型
val mayBeSomePounds = wallet.get("GBP")
val updatedWallet = wallet + ("GBP" -> 20)新的不可变
val tenDollars = "USD"-> 10 Tuple
def increment = (x:Int) => x + 1
List(1,2,3,4).map(increment)
List(1,2,3,4) map increment
String Interpolation
val many = 10000.2345
val amount = s"$many euros"
格式化宽度
val amount = f"$many%12.2f euros"
val amount = s"${many*2} euros"
val printedAmounts = amounts map(m=> s"${m.amount} ${m.currency}")
groupBy
groupBy method that transforms a collection into aMap collection:
val sortedAmounts = amounts groupBy(_.currency)
Scala UnitTest
POM.xml maven依赖文件
·Dependency for the core scala-library:
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.10.0</version>
</dependency>
·Dependency for scalatest (a framework for testing in Scala that supports
JUnit and other styles; we will cover it in detail in Chapter 4, Testing Tools):
<dependency>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_2.10</artifactId>
<version>2.0/version>
<scope>test</scope>
</dependency>
·Dependency for JUnit to use JavaAssert statements in our test case:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
scala-maven-plugin
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
单元测试代码
import org.junit._
import Assert._
class CustomerScalaTest {
@Before
def setUp: Unit = {
}
@After
def tearDown: Unit = {
}
@Test
def testGetCustomerId = {
System.out.println("getCustomerId")
val instance = new Customer()
val expResult: Integer = null
val result: Integer = instance.getCustomerId()
assertEquals(expResult, result)
}
}
Java/Scala Collection转换
./activator console
import java.util.Arrays
val javaList = Arrays.asList(1,2,3,4)
import scala.collection.JavaConverters._
val scalaList = javaList.asScala
val javaListAgain = scalaList.asJava
assert( javaList eq javaListAgain)
JavaBean-style properties
class Company(var name:String)
val sun = new Company("Sun Microsystems")
sun.name
sun.name_=("Oracle")
import scala.beans.BeanProperty
class Company(@BeanProperty var name:String)
val sun = new Company("Sun Microsystems")
sun.getName()
sun.setName("Oracle")
OO
class Customer ( var customerId: Int, var zip: String) {
def this( zip: String) = this(0,zip)
def getCustomerId() = customerId
def setCustomerId(cust: Int): Unit = {
customerId = cust
}
}
val customer = new Customer("123 45")
traits
interface VIPCustomer {
Integer discounts();
}
class Customer(val name:String, val discountCode:String="N" ){
def discounts() : List = List(5)
override def toString() = "Applied discounts: " + discounts.mkString(" ","%, ","% ")
}
trait VIPCustomer extends Customer {
override def discounts = super.discounts ::: List(10)
}
trait GoldCustomer extends Customer {
override def discounts =
if (discountCode.equals("H"))
super.discounts ::: List(20)
else super.discounts ::: List(15)
}
object Main {
def main(args: Array) {
val myDiscounts = new Customer("Thomas","H") with VIPCustomer with GoldCustomer
println(myDiscounts)
}
}
scala> Main.main(Array.empty)
Applied discounts: 5%, 10%, 20%
Note that the order in which traits are stacked is important. They are calling each other from right to left.GoldCustomer is, therefore, the first one to be called.
Static
companion objects
object Main {
def main(args: Array) {
println("Hello Scala World !")
}
}
object Customer {
def apply()= new Customer("default name")
}
class Customer(name:String) {
…
}
exceptions
public class ConversionSample {
static Integer parse(String numberAsString) {
Integer number = null;
try {
number = Integer.parseInt(numberAsString);
} catch (NumberFormatExceptionnfe) {
System.err.println("Wrong format for "+numberAsString);
} catch (Exception ex) {
System.err.println("An unknown Error has occurred");
}
System.out.println("Parsed Number: "+number);
return number;
}
def parse(numberAsString: String) =
try {
Integer.parseInt(numberAsString)
} catch {
case nfe: NumberFormatException =>
println("Wrong format for number "+numberAsString)
case e: Exception => println("Error when parsing number"+
numberAsString)
}
返回值
case nfe: NumberFormatException =>
println("Wrong format for number "+numberAsString); -1
case _: Throwable =>
println("Error when parsing number "+numberAsString)
-1
scala.util.Left orscala.util.Right type
case class Failure(val reason: String)
def parse(numberAsString: String) : Either =
try {
val result = Integer.parseInt(numberAsString)
Right(result)
} catch {
case _ : Throwable => Left(Failure("Error when parsing
number"))
}
String customerLevel = null;
if(amountBought > 3000) {
customerLevel = "Gold";
} else {
customerLevel = "Silver";
}
val amountBought = 5000
val customerLevel = if (amountBought> 3000) "Gold" else "Silver"
Scala的代码风格
IDE
http://docs.scala-lang.org/style/
Eclipse-based (including all the different versions of Eclipse, Typesafe's own bundled version known as Scala IDE as well as more commercial IDEs such as SpringSourceSTS), IntelliJ IDEA, and NetBeans.
SBT
Simple Build Tool (SBT) http://www.scala-sbt.org/
http://www.scala-sbt.org/0.13/tutorial/Hello.html 例子
http://www.scala-sbt.org/0.13/tutorial/Directories.html 目录结构,Build.sbt是sbt的定义文件
SBT plugins
https://github.com/typesafehub/sbteclipse 基于sbt生成eclipse使用的工程文件
https://github.com/mpeltonen/sbt-idea 基于sbt生成IntelliJ使用的工程文件
https://github.com/dcaoyuan/nbscala/wiki/SbtIntegrationInNetBeans 基于sbt生成Netbeans使用的工程文件
plugins.sbt中修改以生成
xsbt-web-plugin (available athttps://github.com/JamesEarlDouglas/xsbt-web-plugin ), a useful plugin to create traditional web apps that runs on a servlet container (such as Jetty).
v Plugins.sbt: addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "0.4.2")
Build.sbt:
name := "SampleProject"
organization := "com.samples"
version := "1.0"
scalaVersion := "2.10.3"
seq(webSettings :_*)
libraryDependencies += "org.mortbay.jetty" % "jetty" % "6.1.22" % "container"
libraryDependencies += "javax.servlet" % "servlet-api" % "2.5" % "provided"
v sbt eclipse生成了eclipse工程
v 启动web工程
> sbt
> container:start
v War包生成 > package
sbt-assembly
https://github.com/sbt/sbt-assembly
v Plugins.sbt addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
v assembly.sbt
import AssemblyKeys._ // put this at the top of the file
assemblySettings
// your assembly settings here
Scalariform
plugins.sbt
addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.0")
SBT中运行compile ortest:compile时,即按照scala风格格式化代码
Scala Worksheets
Eclipse中建立的菜单
每次保存时,可以看到执行的结果
Java基础库上scala的封装例子
http://dispatch.databinder.net/Dispatch.html HttpClient上的封装
build.sbt添加libraryDependencies += "net.databinder.dispatch" %% "dispatch-core" % "0.11.0"
import dispatch._, Defaults._
val request = url("http://freegeoip.net/xml/www.google.com")
val result = Http( request OK as.String)
val resultAsString = result()
def printer = new scala.xml.PrettyPrinter(90, 2)
for (xml <- citiesAsXML)
println(printer.format(xml))
for comprehension orfor expression
for (sequence) yield expression In the preceding code,sequence can contain the following components:
·Generators: They drive the iteration and are written in the following form:
element <- collection
·Filters: They control the iteration and are written in the following form:
if expression
·Definitions: They are local variable definitions and are written in the
following form:
variable = expression
for {
elem <- List(1,2,3,4,5)
} yield "T" + elem
for {
word <- List("Hello","Scala")
char <- word
} yield char.isLower
for {
word <- List("Hello","Scala")
char <- word if char.isUpper
} yield char
or {
word <- List("Hello","Scala")
char <- word
lowerChar = char.toLower
} yield lowerChar
测试
ScalaTest ( www.scalatest.org ) and Specs2 ( etorreborre.github.io/specs2/ ). ScalaCheck framework ( www.scalacheck.org )
Typesafe Activator包含必要的插件,项目根下执行> activator eclipse即生成eclipse工程
import org.scalatest.FunSuite
class Test01 extends FunSuite {
test("Very Basic") {
assert(1 == 1)
}
test("Another Very Basic") {
assert("Hello World" == "Hello World")
}
}
> activator
> test-only scalatest.Test01 (or scalatest.Test01.scala)
>~test-only scalatest.Test02文件修改后自动运行单元测试【continuous mode】
The continuous mode works for the other SBT commands as well, such as~run or~test
作为Junit的单元测试方式运行
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.FunSuite
@RunWith(classOf)
class MyTestSuite extends FunSuite ...
www.seleniumhq.org 功能测试
package scalatest
import org.scalatest._
import org.scalatest.selenium.WebBrowser
import org.openqa.selenium.htmlunit.HtmlUnitDriver
import org.openqa.selenium.firefox.FirefoxDriver
import org.openqa.selenium.WebDriver
class Test08 extends FlatSpec with Matchers with WebBrowser {
implicit val webDriver: WebDriver = new HtmlUnitDriver
go to "http://www.amazon.com"
click on "twotabsearchtextbox"
textField("twotabsearchtextbox").value = "Scala"
submit()
pageTitle should be ("Amazon.com: Scala")
pageSource should include("Scala Cookbook: Recipes")
}
www.scalamock.org
Web框架
alternatives to create web applications range from lightweight frameworks such as Unfiltered, Spray, or Scalatra to full-featured solutions such as the Lift or the Play Frameworks.
http://www.playframework.com/ http://www.playmodules.net
Web Service
Plugins.sbt
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" %"2.4.0")
addSbtPlugin("org.scalaxb" % "sbt-scalaxb" % "1.1.2")
resolvers += Resolver.sonatypeRepo("public")
build.sbt
import ScalaxbKeys._
name:="wssample"
scalaVersion:="2.10.2"
scalaxbSettings
ibraryDependencies += "net.databinder.dispatch" %% "dispatch-core" %"0.11.0"
libraryDependencies += "org.scalatest" %% "scalatest" % "2.0.M7" %"test"
sourceGenerators in Compile <+= scalaxb in Compile
packageName in scalaxb in Compile := "se.wssample"
XML/JSON
val books =
<Library>
<book title="Programming in Scala" quantity="15" price="30.00"
/>
<book title="Scala for Java Developers" quantity="10"
price="25.50" />
</Library>
import scala.xml._
val sameBooks = XML.loadString("""
<Library>
<book title="Programming in Scala" quantity="15"
price="30.00"/>
<book title="Scala for Java Developers" quantity="10"
price="25.50"/>
</Library>
""")
val total = (for {
book <- books \ "book"
price = ( book \ "@price").text.toDouble
quantity = ( book \ "@quantity").text.toInt
} yield price * quantity).sum
val books =
<Library>
{ List("Programming in Scala,15,30.00","Scala for Java
Developers,10,25.50") map { row => row split "," } map { b => <book
title={b(0)} quantity={b(1)} price={b(2)} /> }}
</Library>
import scala.util.parsing.json._
val result = JSON.parseFull("""
{
"Library": {
"book": [
{
"title": "Scala for Java Developers",
"quantity": 10
},
{
"title": "Programming Scala",
"quantity": 20
}
]}
}
""")
Futures and Promises
Scala Improvement Process (SIP)SIP-14-Futures and Promises
http://en.wikipedia.org/wiki/Futures_and_promises
·async { <expression> } : In this construct,<expression> is the code to
be executed asynchronously.
·await { <expression returning a Future> } : This construct is included
in anasync block. It suspends the execution of the enclosingasync block
until the argumentFuture is completed.
async future
Actor
Reactive Systems
http://www.reactivemanifesto.org/
反应式编程
Misc
MongoDB database, we are going to discover how the Casbah Scala toolkit https://github.com/mongodb/casbah
RPEL模式下拷贝部分代码运行
scala> :paste
// Entering paste mode (ctrl-D to finish)
页:
[1]