如何将Scala案例类和集合连接到Java
我们在尝试使用Java中的Scala代码时遇到了问题。我们正在寻找一种方法来自动桥接各种Scala和java集合,而无需在java代码中显式转换。当只有很少的地方时,这样做是合理的,但是如果它分布广泛并且不断添加新的scala类,那么它就变得不切实际了 例如,在Scala代码中,我们有一些类似的类(其中很多): 当我们想用Java编写类似的代码时,它会变得非常麻烦,我们需要在所有地方添加许多辅助锅炉板:如何将Scala案例类和集合连接到Java,java,scala,scala-java-interop,Java,Scala,Scala Java Interop,我们在尝试使用Java中的Scala代码时遇到了问题。我们正在寻找一种方法来自动桥接各种Scala和java集合,而无需在java代码中显式转换。当只有很少的地方时,这样做是合理的,但是如果它分布广泛并且不断添加新的scala类,那么它就变得不切实际了 例如,在Scala代码中,我们有一些类似的类(其中很多): 当我们想用Java编写类似的代码时,它会变得非常麻烦,我们需要在所有地方添加许多辅助锅炉板: // JAVA // create a product HashMap<String,
// JAVA
// create a product
HashMap<String, String> attributes = new HashMap<String, String>();
attributes.put("my-attribute","my-value");
// create a scala collection
scala.collection.immutable.Map<String, String> scalaAttributes = Conversions.toScalaImmutableMap(attributes);
// create a product
Product p = Product("id","group",scalaAttributes)
// create a scala sequence of product
ArrayList<Product> dataFeedsProducts = new ArrayList<Product>();
dataFeedsProducts.add(Product);
Seq<Product> seq = JavaConversions.asScalaBuffer(dataFeedsProducts).seq();
fooWithProducts(seq)
// SCALA helpers
public class Conversions {
//https://stackoverflow.com/questions/11903167/convert-java-util-hashmap-to-scala-collection-immutable-map-in-java/11903737#11903737
@SuppressWarnings("unchecked")
/**
* Transforms a java map to a scala immutable map
*/
public static <K, V> scala.collection.immutable.Map<K, V> toScalaImmutableMap(java.util.Map<K, V> javaMap) {
final java.util.List<scala.Tuple2<K, V>> list = new java.util.ArrayList(javaMap.size());
for (final java.util.Map.Entry<K, V> entry : javaMap.entrySet()) {
list.add(scala.Tuple2.apply(entry.getKey(), entry.getValue()));
}
final scala.collection.Seq<Tuple2<K, V>> seq = scala.collection.JavaConverters.asScalaBufferConverter(list).asScala().toSeq();
return (scala.collection.immutable.Map<K, V>) scala.collection.immutable.Map$.MODULE$.apply(seq);
}
/**
* transforms a scala map to the java counterpart
*/
public static <K,V> java.util.Map<K,V> mapAsJavaMap(scala.collection.immutable.Map<K,V> m) {
if (m == null) {
return null;
}
return JavaConversions.mapAsJavaMap(m);
}
public static<A> Seq<A> asScalaSeq(java.util.List<A> l) {
return JavaConversions.asScalaBuffer(l).toSeq();
}
}
//JAVA
//创建产品
HashMap attributes=新的HashMap();
属性。放置(“我的属性”、“我的价值”);
//创建scala集合
scala.collection.immutable.Map scalaAttributes=Conversions.toScalaImmutableMap(属性);
//创建产品
产品p=产品(“id”、“组”、ScalaAttribute)
//创建产品的scala序列
ArrayList dataFeedsProducts=新的ArrayList();
dataFeedsProducts.add(产品);
Seq-Seq=JavaConversions.asScalaBuffer(dataFeedsProducts.Seq();
食品产品(续)
//SCALA助手
公共类转换{
//https://stackoverflow.com/questions/11903167/convert-java-util-hashmap-to-scala-collection-immutable-map-in-java/11903737#11903737
@抑制警告(“未选中”)
/**
*将java映射转换为scala不可变映射
*/
公共静态scala.collection.immutable.Map toScalaImmutableMap(java.util.Map javaMap){
final java.util.List List=new java.util.ArrayList(javaMap.size());
for(最终的java.util.Map.Entry条目:javaMap.entrySet()){
添加(scala.Tuple2.apply(entry.getKey(),entry.getValue());
}
final scala.collection.Seq Seq=scala.collection.JavaConverters.asScalaBufferConverter(list.asScala().toSeq();
返回(scala.collection.immutable.Map)scala.collection.immutable.Map$.MODULE$.apply(seq);
}
/**
*将scala映射转换为java对应映射
*/
public static java.util.Map mapAsJavaMap(scala.collection.immutable.Map m){
如果(m==null){
返回null;
}
返回JavaConversions.mapAsJavaMap(m);
}
公共静态Seq asScalaSeq(java.util.List l){
返回JavaConversions.asScalaBuffer(l.toSeq();
}
}
我们想知道是否有一种方法可以为这些Scala习惯用法注释Scala代码或自动生成等效的Java对应接口。大多数用Scala编写但应该同时从Scala和Java使用的框架都有一个单独的Java API。例如,Akka、Play和Spark就是这样 这并不是因为从Java实例化Scala类是完全不可能的,而是因为它非常不惯用、繁琐和烦人。因此,设计师没有将Java数据结构转换为Scala数据结构的负担转移给API的用户,而是简单地创建一个单独的Java API,并一次性解决所有转换和工厂方法的问题 也就是说,而不是
- 在Scala中编写库并仅提供Scala API
- 用Java编写C_1类,使用Scala API,用转换污染代码(痛苦-1)
- 用Java编写类C\u n,使用Scala API,用转换污染代码(痛苦-n)
- 在Scala中编写一个库,首先提供Scala API
- 将
包添加到您的库中,实现一个单独的JavaAPI,仍然使用Scala(pain singleton)foobar.api.java
- 用Java API编写C_1类(nice-and-pleaster-1)
- 使用Java API编写类C_n(nice-and-pleaster-n)
产品
s:
// somewhere in api.java
def product(
id: String,
grp: String,
attrToVal: java.util.HashMap[String, String]
): Product = /* use `JavaConversions`, invoke constructor */
2) 提供可从Java调用的fooWithProducts
版本
没有任何转换:
// in api.java
def fooWithProducts(ps: java.util.List[Product]): Foo =
// Convert java List to scala Seq here,
// call original `fooWithProducts`
对API中应该出现的每个类和方法都这样做。要使其正常工作,API必须具有最小的表面积,并且与库的内部结构相比,API必须集中且相对简单。您看到了吗?@LucaT。您所链接的内容似乎更适合java->scala方向,因为scala有隐式转换,所以这就不那么痛苦了。
// in api.java
def fooWithProducts(ps: java.util.List[Product]): Foo =
// Convert java List to scala Seq here,
// call original `fooWithProducts`