java scala_Java开发人员Scala简介

java scala

Scala使用与Java完全兼容并在JVM上运行的简洁语法,将面向对象和功能编程范例结合在一起。 支持函数式编程风格,尤其是现在不希望在2012年JavaSE 8之前不将其添加到Java中的Lambda表达式,可以帮助减少您需要编写的样板代码的数量,可以说使得集中精力更加容易在手头的任务上。 本文介绍了Scala。

要开始使用,只需安装最新Scala发行牛逼 ypesafe栈 ,打开命令提示符,然后键入“阶”:这将启动REPL(读-EVAL打印循环)交互式编程环境。 现在您可以输入您的第一个Scala行:

scala> val哥伦布:Int = 1492
哥伦布:国际= 1492

我们刚刚声明了一个Int类型的变量,其值为1492,就像我们在Java中使用“ Int columbus = 1492;”所做的那样。 这里的区别与将类型放在Scala中的变量后面的反向语法不同,在于“ val”将变量明确声明为不可变。 如果我们尝试修改它:

scala> columbus = 1500
<console>:8: error: reassignment to val
  columbus = 1500
         ^ 

注意消息是如何精确显示错误所在的行。 尝试再次声明该变量,但是这次将其声明为“ var”以使其可变。 顺便说一下,编译器足够聪明,可以知道1492是整数,因此您根本不需要指定类型:

scala> var columbus = 1492
columbus: Int = 1492

scala> columbus = 1500
columbus: Int = 1500

继续,让我们定义一个类:

scala> case class Employee( name:String="guest", age:Int=30, company:String = 
"DevCode" )
defined class Employee

我们定义了一个Employee类,它具有3个不可变的字段,名称,年龄和公司均为默认值。 “ case”一词类似于Java中的switch语句,但更为灵活。 这意味着该类具有一种额外的模式匹配机制以及其他功能,其中包括一种用于创建实例的工厂方法(无需使用“ new”关键字来创建实例)。 同样,也无需创建默认的吸气剂。 与Java不同,变量默认情况下是公共的(不受保护),并且Scala为以变量本身名称命名的公共变量创建一个getter。 如果需要,可以通过在参数前面使用“ var”来使字段可变和/或私有(例如,案例类Person(private var name:String))。

让我们以不同的方式创建一些实例以展示各种功能,例如命名和默认参数(从Scala 2.8开始可用):

scala> val guest = Employee()
guest: Employee = Employee(guest,30,DevCode)

scala> val guestAge = guest.age // (the default getter for the age variable)
guestAge: Int = 300

scala> val anna = Employee("Anna")
anna: Employee = Employee(Anna,30,DevCode)

scala> val thomas = Employee("Thomas",41)
thomas: Employee = Employee(Thomas,41,DevCode)

scala> val luke = Employee("Luke", company="LucasArt")
luke: Employee = Employee(Luke,30,LucasArt)

scala> val yoda = luke.copy("Yoda", age=800)
yoda: Employee = Employee(Yoda,800,LucasArt)

但是,以下

scala> val darth = Employee("Darth", "DevCode")
<console>:9: error: type mismatch;
found : java.lang.String("DevCode")
required: Int
Error occurred in an application involving default arguments.
    val darth = Employee("Darth", "DevCode")
                     ^

...不起作用(不是因为在DevCode上没有使用Darth!),而是因为构造函数期望在该位置使用age参数,因为该参数未明确命名。

现在,我们将继续进行收藏,因为那是真正令人兴奋的地方。

使用泛型(从Java 5开始),例如,Java可以通过编写以下代码来遍历整数列表:

List<Integer> numbers = new arrayList<Integer>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
for(Integer n:numbers) {
System.out.println("Number "+n);
} 

产生

1号
2号
3号

Scala集合系统地区分不可变集合和可变集合,但默认情况下通过构造不可变集合来鼓励不可变。 它们通过从此类操作返回新集合而不是对其进行修改来模拟添加,更新或删除。

可以编写与以前的Java代码等效的Scala代码:

scala> val numbers = List(1,2,3)
numbers: List[Int] = List(1, 2, 3)

scala> for (n <- numbers) println("Number "+n)
Number 1
Number 2
Number 3

这种“ for”循环构造非常类似于Java的命令式编程风格。 用Scala(以及JVM上的许多语言,例如Groovy,JRuby或Jython)和Scala编写它的另一种方法涉及使用lambda表达式(有时称为闭包)的更具功能性的样式。 简而言之,Lambda只是可以作为参数传递的函数。 这些函数将参数作为输入(在我们的示例中为“ n”整数),并返回其主体的最后一条语句作为其结果。 它们的形式

functionName { input =>
                 body
                }

scala> numbers.foreach { n:Int =>     // just press Enter to continue on the next line
   | println("Number "+n)
   | }
Number 1
Number 2
Number 3

在这种情况下,主体只有一个语句(println ...),因此返回Unit,即“空结果”与Java中的void大致等效,但“ void”不返回任何内容。

假设我们要操纵和转换元素,而不仅仅是输出数字列表。 在这种情况下,我们希望调用将产生结果列表的方法,以便以后使用。 让我们尝试一些例子:

scala> val reversedList = numbers.reverse
reversedList: List[Int] = List(3, 2, 1)

scala> val numbersLessThan3 = numbers.filter { n => n < 3 }
numbersLessThan3: List[Int] = List(1, 2)

scala> val oddNumbers = numbers.filterNot { n => n % 2 == 0 }
oddNumbers: List[Int] = List(1, 3)

scala> val higherNumbers = numbers.map { n => n + 10 }
higherNumbers: List[Int] = List(11, 12, 13)

最后的转换“地图”非常有用; 它将闭包应用于列表的每个元素,其结果是一个包含每个转换元素的大小相同的列表。

我们在这里要介绍的最后一种方法是“ foldLeft”方法,该方法将状态从一个元素传播到另一个元素。 例如,要对列表中的元素求和,您需要对其进行累加并跟踪从一个元素到下一个元素的中间计数器:

scala> val sumOfNumbers = numbers.foldLeft(0) { (total,element) =>
   | total + element
   | }
sumOfNumbers: Int = 6 

foldLeft的第一个参数给出的值0是初始值(这意味着将函数应用于第一个列表元素时,total = 0)。 符号(total,element)表示一个Tuple2,它在Scala中是一个具有2个元素的元组(例如,表示3D空间坐标,通常引用Tuple3(x,y,z)等很有用...)。 请注意,为了求和,Scala API实际上提供了一个“ sum”方法,因此可以写出最后一条语句:

scala> val sumOfNumbers = numbers.sum
sumOfNumbers: Int = 6 

您可以从scaladoc API中检查更多的这些集合转换方法。 您也可以链接这些方法(例如,numbers.reverse.filter ...)以获得更简洁的代码,尽管它可能会影响可读性。

最后,以(_ + 10)的形式存在等效于{n => n + 10}的较短符号,这意味着如果您所调用的方法仅暗示了输入参数,则不必声明该输入参数。 在我们的例子中,“ n”被称为匿名变量,因为您可以随意调用它,例如“ x”或“ number”,因此下划线表示您需要用集合中的每个元素填充空格。 (Groovy保留单词“ it”而不是_,Python使用“ self”)。

scala> val higherNumbers = numbers.map(_+10)
higherNumbers: List[Int] = List(11, 12, 13)  

在对整数进行基本操作之后,我们准备进入涉及更复杂对象的集合转换,例如使用上面定义的Employee类:

scala> val allEmployees = List(luke,anna,guest,yoda,thomas)
allEmployees: List[Employee] = List(Employee(Luke,30,LucasArt), 
Employee(Anna,30,DevCode), Employee(guest,30,DevCode),
Employee(Yoda,800,LucasArt), Employee(Thomas,41,DevCode))

从这5个元素的列表中,我们可以通过应用过滤器来保留DevCode雇员,该过滤器将保留匿名函数为其返回True的雇员:

scala> val devcodeEmployees = allEmployees.filter { _.company == "DevCode" }
devcodeEmployees: List[Employee] = List(Employee(Anna,30,DevCode), 
Employee(guest,30,DevCode), Employee(Thomas,41,DevCode))

scala> val oldEmployees = allEmployees.filter(_.age > 100).map(_.name)
oldEmployees: List[String] = List(Yoda)

想象一下,我们拥有的allEmployees集合是从SQL查询获得的结果集,类似于“ SELECT * FROM employee WHERE company ='DevCode'”。 现在,我们可以通过将List [Employee]转换为Map,其中键是公司名称,而值是该公司所有雇员的列表,来按公司对雇员进行排序:

scala> val sortedEmployees = allEmployees.groupBy(_.company)
sortedEmployees: scala.collection.immutable.Map[String,List[Employee]] = Map(DevCode -
> List(Employee(Anna,30,DevCode), Employee(guest,30,DevCode),
Employee(Thomas,41,DevCode)), LucasArt -> List(Employee(Luke,30,LucasArt),
Employee(Yoda,800,LucasArt)))

作为进一步处理存储为该(键-值)哈希表值的每个列表的示例,我们可以想象计算每个公司的员工平均年龄。

实际上,这意味着我们必须对每个列表的每个员工的“年龄”字段求和,然后除以该列表中的员工数量。 让我们首先为DevCode做一下:

scala> devcodeEmployees
res4: List[Employee] = List(Employee(Anna,30,DevCode), Employee(guest,30,DevCode), 
Employee(Thomas,41,DevCode))

scala> val devcodeAges = devcodeEmployees.map(_.age)
devcodeAges: List[Int] = List(30, 30, 41)

scala> val devcodeAverageAge = devcodeAges.sum / devcodeAges.size
devcodeAverageAge: Int = 33

回到我们的Map的更一般的情况(键:字符串->值:列表[雇员]),我们现在可以通过写几行来汇总和计算每个公司的平均年龄:

scala> val averageAgeByCompany = sortedEmployees.map{ case(key,value)=>
   | value(0).copy(name="average",age=(value.map(_.age).sum)/value.size)}
averageAgeByCompany: scala.collection.immutable.Iterable[Employee] = 
List(Employee(average,33,DevCode), Employee(average,415,LucasArt))

“ case(key,value)”是Scala提供的功能非常强大的模式匹配机制的一个示例。 有关更多说明,请参见Scala文档。

现在我们完成了。 我们刚刚写的是一个小的“ Map Reduce”算法。 由于每个公司的员工总数完全独立于其他公司,因此该算法非常易于并行化。

附录中给出了Java和Scala中算法的等效实现。

参考资料

类型安全堆栈。

附录

Map Reduce:Java

public class Employee {

              final String name;
              final Integer age;
              final String company;

              public Employee(String name, Integer age, String company) {
                          this.name = name == null ? "guest" : name;
                          this.age = age == null ? 30 : age;
                          this.company = company == null ? "DevCode" : company;
              }

              public String getName() {
                          return name;
              }

              public int getAge() {
                          return age;
              }

              public String getCompany() {
                          return company;
              }

              @Override
              public String toString() {
                            return "Employee [name=" + name + ", age=" + age + ",
company="
                                                     + company + "]";
              }
}

class Builder {
              String name, company;
              Integer age;

              Builder(String name) {
                          this.name = name;

              }

              Employee build() {
                          return new Employee(name, age, company);
              }

              Builder age(Integer age) {
                          this.age = age;
                          return this;
              }

              Builder company(String company) {
                          this.company = company;
                          return this;
              }
}

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimaps;

public class MapReduce {

              public static final void main(String[] args) {
                            Employee guest = new Builder("Guest").build();
                            Employee anna = new Builder("Anna").build();
                            Employee thomas = new Builder("Thomas").age(41).build();
                            Employee luke = new
Builder("Luke").company("LucasArt").build();
                            Employee yoda = new
Builder("Yoda").age(800).company("LucasArt").build();

                            Collection<Employee> employees = new ArrayList<Employee>();
                            employees.add(guest);
                            employees.add(anna);
                            employees.add(thomas);
                            employees.add(luke);
                            employees.add(yoda);

                            ImmutableListMultimap<String, Employee>
personsGroupByCompany = Multimaps.index(employees, new Function<Employee,
String>() {

                             public String apply(Employee person) {
                               return person.getCompany();
                             }

                            });

                            for(String company: companyNamesFromMap) {
                                         List<Employee> employeesForThisCompany =
personsGroupByCompany.get(company);
                                         int sum = 0;
                                         for(Employee employee:
employeesForThisCompany) {
                                                    sum+= employee.getAge();
                                         }
                                         averageAgeByCompany.add(new
Employee("average",sum/employeesForThisCompany.size(),company));
                       }
                       System.out.println("Result: "+averageAgeByCompany);

           }
}

MapReduce.scala:

case class Employee(name: String = "guest", age: Int = 30, company: String = "DevCode")

  val guest = Employee()
  val anna = Employee("Anna")
  val thomas = Employee("Thomas", 41)
  val luke = Employee("Luke", company = "LucasArt")
  val yoda = luke.copy("Yoda", age = 800)

  val allEmployees = List(luke, anna, guest, yoda, thomas)
  val sortedEmployees = allEmployees.groupBy(_.company)
  val averageAgeByCompany = sortedEmployees.map { case (key, value) =>
      value(0).copy(name = "average", age = (value.map(_.age).sum) / value.size)
  }
  println("Result: "+averageAgeByCompany)
 }
}

翻译自: https://www.infoq.com/articles/scala-for-java-devs/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

java scala

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值