我正在学习Scala,并且有一个Java项目可以迁移到Scala。我想通过逐个重写类并检查新类没有破坏项目来迁移它。
该Java项目使用java.util.List
和java.util.Map
。在新的Scala类中,我想使用Scala
List
并Map
拥有漂亮的Scala代码。
问题在于新类(在Scala中添加了新类)无法与现有Java代码无缝集成:Java需要java.util.List
,Scala需要自己的scala.List
。
这是问题的简化示例。有 Main , Logic , Dao类 。他们在一行中互相调用: Main- > Logic-> Dao。
public class Main {
public void a() {
List<Integer> res = new Logic().calculate(Arrays.asList(1, 2, 3, 4, 5));
}
}
public class Logic {
public List<Integer> calculate(List<Integer> ints) {
List<Integer> together = new Dao().getSomeInts();
together.addAll(ints);
return together;
}
}
public class Dao {
public List<Integer> getSomeInts() {
return Arrays.asList(1, 2, 3);
}
}
在我的情况下, Main 和 Dao 类是框架类(我不需要迁移它们)。Class Logic 是业务逻辑,它将从Scala的出色功能中受益匪浅。
我需要在Scala中重写 Logic 类,同时保持 Main 和 Dao 类的完整性。最好的重写看起来像(不起作用):
class Logic2 {
def calculate(ints: List[Integer]) : List[Integer] = {
val together: List[Integer] = new Dao().getSomeInts()
together ++ ints
}
}
理想的行为: Logic2 中的列表是本机Scala列表。所有进/出java.util.Lists
都自动装箱/拆箱。但这是行不通的。
相反,这确实可行(由于scala-javautils(GitHub)):
import org.scala_tools.javautils.Implicits._
class Logic3 {
def calculate(ints: java.util.List[Integer]) : java.util.List[Integer] = {
val together: List[Integer] = new Dao().getSomeInts().toScala
(together ++ ints.toScala).toJava
}
}
但是看起来很丑。
如何在Java <-> Scala之间实现列表和地图的透明魔术转换(无需执行toScala / toJava)?
如果不可能,那么使用java.util.List
和朋友迁移Java-> Scala代码的最佳实践是什么?
相信我; 您不 希望
来回透明转换。这正是这些scala.collection.jcl.Conversions
功能试图执行的操作。在实践中,这会引起很多头痛。
这种方法的问题根源在于,Scala会根据需要自动注入隐式转换,以使方法调用起作用。这可能会带来一些非常不幸的后果。例如:
import scala.collection.jcl.Conversions._
// adds a key/value pair and returns the new map (not!)
def process(map: Map[String, Int]) = {
map.put("one", 1)
map
}
对于Scala集合框架的新手,甚至不可变集合的概念,此代码不会完全不合时宜。不幸的是,这是完全错误的。此函数的结果是 同
一张图。对的调用会put
触发对的隐式转换java.util.Map<String, Int>
,该转换很乐意接受新值并被立即丢弃。原始文件map
未经修改(实际上是不可变的)。
豪尔赫·奥尔蒂斯(Jorge Ortiz)最好地指出,您仅应出于以下两个目的之一来定义隐式转换:
A
并且B
这些类型无关。您可以定义一个转换,A => B
当且 仅 当您希望拥有A <: B
(<:
表示“子类型”)时。由于java.util.Map
显然不是与我们层次结构中的任何事物都无关的新类型,因此我们不能属于第一个附带条件。因此,我们唯一的希望是我们的转换Map[A, B] => java.util.Map[A, B]
有资格获得第二个。但是,Scala
Map
继承自绝对没有任何意义java.util.Map
。它们实际上是完全正交的接口/特征。如上所述,尝试忽略这些准则几乎总是会导致奇怪和意外的行为。
事实是javautils
asScala
和asJava
方法旨在解决这个确切的问题。从中的javautils中有一个隐式转换(实际上有许多转换)Map[A, B] => RichMap[A, B]
。
RichMap
是javautils定义的全新类型,因此它的唯一目的是向中添加成员Map
。特别是,它添加了asJava
方法,该方法返回一个包装器映射,该包装器实现java.util.Map
并委托给您的原始Map
实例。这使过程更加明确,并且出错的可能性也大大降低。
换句话说,使用asScala
和asJava
是
最佳做法。在生产应用程序中独立走过这两条路之后,我可以直接告诉您javautils方法更安全,更容易使用。不要仅仅为了节省自己的8个字符而试图规避其保护!
在这个问题中,我必须调用一个第三方Java库,该库期望,其结果来自Scala例程返回。 我会将Scala-Future封装到一个新的Java-Future中,但是没有办法实现Java-Future方法< code > def cancel(mayinterruptirunning:Boolean):Boolean ,因为它会中断封装的Scala-Future(否则请告诉我)。 我该如何解决这个问题
我有一个java map:
问题内容: 我想转换一个从Java中8是这样的: 因为我有一个字符串列表,所以我想创建一个Map,键是列表的字符串,值是Integer(零)。 我的目标是计算字符串列表的元素(在我的代码中稍后)。 我知道以“旧”方式进行转换很容易; 但我想知道是否还有Java 8解决方案。 问题答案: 如前所述,参数必须是函数,因此必须更改为(可以使用任何其他参数名称代替)。 但是请注意,如果中存在重复项,此操作
基本上我的问题分为两部分。 > 我想知道将要操纵像素并将特定颜色转换为透明像素的首选/快速方法。 我想知道我是否能够使用这个“BuffereImage”,而不必将其保存为支持“png”等透明度的文件格式 我找到了一种设置单个像素的方法 这儿呢 正如它所提到的,这是一种“缓慢的方法” 我发现这个线程Java:用透明像素填充BufferedImage 哪一条评论提到了“int[]”和操纵像素。 本质上
问题内容: 我已经读过Clojure vs. Scala的各种论述,而我意识到两者都有自己的位置。关于将Clojure和Scala进行比较时,有一些注意事项尚未得到完整的解释: 1.)两种语言中哪一种通常 更快 ?我意识到这从一种语言功能到另一种语言功能都会有所不同,但是对性能进行总体评估会有所帮助。例如:我知道Python字典的速度非常快。但作为一个整体,它是一个 多 比Java慢语。我不想和C
问题内容: 我需要在Java中实现一个返回Scala的方法。 但是我遇到这个错误: 到目前为止,这是我的代码: 但似乎没有提供将其转换为的可能性。 问题答案: 我需要JavaConverters来解决这个问题。