Alternative to Collectors.groupingBy() for scala - java

In Java I have something like:
Collectors.groupingBy((Re r) -> return r.pName)
And it works properly. Now I'm trying to get the same thing into scala, like:
Collectors.groupingBy((r:Re) => return r.pName)
but then I get stuff like
cannot resolve reference groupingBy with such signature
cannot resolve symbol groupingBy
unspecified value parameters Collector
unspecified value parameters Supplier
Let me know if you need any more info/code, and I'll create some dummy example since I'm not allowed to post the exact code.
Update based on #Vladimir Matveev answer:
pName should be String, but if I write new java.util.function.Function[Re, java.lang.String] then I get a
type mismatch;
found : java.util.function.Function[Re,String]
required: java.util.function.Function[_ >: Re, _ <: ?0(in value x$1)(in value x$1)(in value x$1)(in value x$1)]

Java lambdas are "implementors" of arbitrary functional interfaces (in this particular case Collectors.groupingBy() accepts java.util.function.Function. Scala anonymous functions, however, are instances of some class implementing scala.FunctionX trait. Consequently, you can't use Scala functions for arbitrary functional interfaces (but there are plans to allow that, as far as I know).
You need to create an anonymous class extending java.util.function.Function explicitly:
Collectors.groupingBy(new java.util.function.Function[Re, ???] {
def apply(r: Re) = r.pName
})
(you need to put correct type of pName instead of ???, of course).
If you're doing this often, you can define an implicit conversion for Scala's T => U to java.util.function.Function[T, U]:
implicit class FunctionWrapper[T, U](f: T => U) extends java.util.function.Function[T, U] {
def apply(x: T): U = f(x)
}
Then (given that this implicit is in scope) you can use it like you tried initially:
Collectors.groupingBy((r: Re) => r.pName)
Update I have no idea why your error happens (probably because of some incompatibilities between Scala and Java generics), but if you specify all types explicitly it does work:
scala> Collectors.groupingBy[Re, String](new JFunction[Re, String] {
| def apply(r: Re) = r.pName
| })
res2: java.util.stream.Collector[Re, _, java.util.Map[String,java.util.List[Re]]] = java.util.stream.Collectors$CollectorImpl#4f83df68
(JFunction is an alias for java.util.function.Function).
The variant with an implicit adaptor looks nicer (but still requires explicit type annotations):
scala> Collectors.groupingBy[Re, String]((r: Re) => r.pName)
res4: java.util.stream.Collector[Re, _, java.util.Map[String,java.util.List[Re]]] = java.util.stream.Collectors$CollectorImpl#71075444

Related

Java fails to properly infer stream type without apparently redundant typecast

I'm doing a series of streaming operations to flatten what's effectively a 2D array.
Arrays.stream(attributes)
.map(Attribute::getCommand)
.filter(Optional::isPresent)
.map(Optional::get)
.flatMap((array) -> (Arrays.stream((String[]) array)))
.toArray(String[]::new)
Where Attribute conforms to the following interface:
public interface Attribute<T> {
Optional<String[]> getCommand();
}
However, the final flatMap() call isn't operating as expected.
.flatMap((array) -> (Arrays.stream((String[]) array))) works just fine.
.flatMap((array) -> (Arrays.stream(array))) fails to compile with java: no suitable method found for stream(java.lang.Object).
.flatMap(Arrays::stream) fails to compile with java: incompatible types: cannot infer type-variable(s) T (argument mismatch; java.lang.Object cannot be converted to T[]).
It seems to me that the type should be inferred just fine though. IntelliJ agrees and marks the cast as redundant and shows no compile errors with any of the three implementations. Why does Java require this apparently redundant typecast?
I additionally tried the following minimalist implementation:
import java.util.Arrays;
import java.util.Optional;
public class Streaming {
public static void main(String[] args) {
Optional<String[]>[] myarray = new Optional[]{Optional.of(new String[]{"Hello", "world"}),
Optional.empty(), Optional.of(new String[]{"Foo"})};
System.out.println(Arrays.toString(Arrays.stream(myarray).filter(Optional::isPresent).map
(Optional::get).flatMap(Arrays::stream).toArray(String[]::new)));
}
}
And it works just fine with all three implementations, outputting the expected [Hello, world, Foo].
Edit:
This was marked as a duplicate of this question. I may be wrong, but it seems that there's a distinction since this the type is specified in a more explicit manner. Notably, IntelliJ agrees that the cast is necessary in the example provided on said post, but not for my code. If I am mistaken, please let me know.
Edit:
Per request, the declaration of attributes is Attribute[] attributes = new Attribute[]{...} where ... is a variety of implementations of Attribute.
Attribute is a generic class (I wonder why as T is not used).
If you have this error it means that you declared a raw type of that such as :
Attribute[] attributes = ...;
For a raw type, the return type of getCommand() that is declared as Optional<String[]> becomes just Optional.
Declare Attribute as a generic type, for example : Attribute<String>[] attributes = ...; and this should compile without the cast or just remove the parameterized type T if it is not required.

Generic implementation von java.util.Comparator in Scala

I am using twirl templates with Java and Scala. So I am trying to sort a List in the template, but I do not know how to override the Comparator method.
My List contains objects of a class designed like:
class Foo extends BaseFoo<Foo>
The class BaseFoo does have a method called
public String FooName() {/*returns some Name of Foo*/}
In my scala twirl template it looks like:
source: java.util.Collection[_ <: BaseFoo[_]]
No in the twirl template I am trying to sort it:
#Collections.sort(
new util.ArrayList[_ <: BaseFoo[_]](source),
new Comparator[_ <: BaseFoo[_]] {
override def compare(o1: BaseFoo, o2: BaseFoo) = {
return o1.FooName.compareTo(o2.FooName);
}
})
But this seems not to compile:
class type required but java.util.ArrayList[_ <: BaseFoo[_]] found
Not a direct answer, but given that you state that you have a list of Foo objects, the straight forward solution seems to be to use
source: java.util.Collection[_ <: Foo[_]]
or something alike!
Meaning: when the list contains Foo objects, what does it matter if those descend from Object or from FooBase?!
You could convert your source to a Scala collection type and then just call .sortBy on it. No need for Comparators:
import collection.JavaConverters._
source.asScala.toSeq.sortBy(_.FooName)

How to pass nested scala object reference in Java?

There have been some questions answered on this before.
How can I pass a scala object reference around in Java
How can I use a Scala singleton object in Java?
But my problem is that I have nested scala objects, something like:
object Criteria {
object ActionCriteria {
case class Action (parameter: String) {
def this(parameter: String) = { this(paramerter) }
}
object Action {
def apply(parameter: String): Action = { apply(parameter) }
}
}
}
In java I then need to create a list of Actions. I have tried this... to no avail:
import Criteria.ActionCriteria.Action$
....
List<Criteria.ActionCriteria.Action$.MODULE$> actions = new ArrayList<>();
As well as a bunch of other combinations like adding $.MODULE$ with every object. Right now I am getting the following error:
error: cannot find symbol Criteria.ActionCriteria
List<Criteria$ActionCriteria$Action> actions = new ArrayList<>();
Seems to work fine. Found this with Scala REPL:
scala> classOf[Criteria.ActionCriteria.Action]
res1: Class[Criteria.ActionCriteria.Action] = class Criteria$ActionCriteria$Action
If you want the type of Action object, not case class (highly unlikely, but for the sake of completeness):
scala> Criteria.ActionCriteria.Action.getClass
res2: Class[_ <: Criteria.ActionCriteria.Action.type] = class Criteria$ActionCriteria$Action$
The difference is caused by Scala expecting Action to be a type in classOf[Action], so it returns the type corresponding to the case class. When you use Action in a context where a value is expected, it returns the singleton instance instead, so you can call standard Java method getClass to get the type of object Action.
In case you need other types:
Criteria$ cm = Criteria$.MODULE$;
Criteria.ActionCriteria$ cacm = Criteria.ActionCriteria$.MODULE$;
Criteria$ActionCriteria$Action$ cacam = Criteria$ActionCriteria$Action$.MODULE$;
Criteria$ActionCriteria$Action caca = new Criteria$ActionCriteria$Action("Foo");
Criteria.ActionCriteria$ is breaking the pattern here. Why? According to Iulian Dragos' comment under bug SI-2034 this is a special case:
since objects are "the equivalent of static" in the Java world, we
wanted to make it easier for Java code to use static inner classes.
When there's only one level of nesting, there's a guaranteed
companion: every top-level object gets a mirror class (if there isn't
one) that creates static forwarders to module methods (that's how one
can run a main method defined inside an object). Therefore, a
special case for one-level nesting: those classes use the flattened
name (without a $ suffix) as outer_name. So, Java code can say new Outer.Inner.
Summary
For every level of nesting other than first you replace . with $ in your class names
If the target type is also an object you add $ at the end
If you want an instance you add .MODULE$

What's the easiest way to convert a Scala reflection MethodSymbol/MethodSignature to a Java Method?

Scala reflection is designed for both compilation time and run time. So it can identify polymorphic method more effectively than Java (see my previous post In Scala Reflection, How to get generic type parameter of a concrete subclass?), which suffers from type erasure.
However, this method can only be invoked using Scala reflection's mirror, which is slightly slower than its java counterpart, I would like to know if there is an easy way to convert Scala MethodSymbol, which is returned by Type.members:
import import scala.reflect.runtime.universe._
val tpe = typeTag[String].tpe
val methodSymbol = tpe.method("size": Name)
or MethodSignature, which is returned by Type.member.SignatureIn(Type):
val methodSignature = methodSymbol.typeSignatureIn(tpe)
to a Java method that can be directly invoked through Java reflection API:
val size = method.invoke("abc")
size: Int = 3
Is it possible?
Here's one way to simulate Java-style invocation.
object ScalaMethodUtil {
import scala.reflect.runtime.universe._
def invoke(m: MethodSymbol)(o: Any)(args: Any*): Any = {
val mirror = runtimeMirror(o.getClass.getClassLoader).reflect(o)
mirror.reflectMethod(m)(args: _*)
}
}

How to detect the java class from a generic JAXBElement<? extends >

I'm working on a WebService built from an existing WSDL, using NetBeans and Glassfish.
NetBeans has created the needed classes from the given WSDL.
The WSDL define some base data types (for example BaseType) and other data types which extend them. (for example ExtType1, ExtType2 ...)
Some of the SOAP functions described in WSDL accept parameters of BaseType type, so it could be possibile to use extended types as parameters, too.
In the web service client, written in PHP, I can invoke a method using a base type parameter:
$response = $ws->__soapCall(
'myFunctionName',
array('theParameter' => array (
'BaseTypeField1' => 'some value',
'BaseTypeField2' => 'some other value'
)
)
);
or using an extended type parameter
$response = $ws->__soapCall(
'myFunctionName',
array('theParameter' => array (
'BaseTypeField1' => 'some value',
'BaseTypeField2' => 'some other value',
'ExtTypeField1' => 'some value',
'ExtTypeField2' => 'some other value'
)
)
);
Now in netbeans generated classes I have an object of type JAXBElement<? extends BaseType>, where a BaseType object is expected.
The question is: how can I determine, from within the Java web method call, if the parameter object from the web service client is a BaseType one or one of his extended types (and which of those)?
I have tried to retrieve some class data information for that object, but it always says it's a BaseType, so I cannot know if ExtTypeField1 and ExtTypeField2 are available for sure.
Thanks
Given that you have something like this JAXBElement<? extends BaseType> object you can determine the type of the value as follow:
Class<? extends BaseType> klass = object.getValue().getClass();
Now from there you can do something based on the object type but this is not always the best way to go. What you will probably want is more something like this:
BaseType value = object.getValue();
if (value instanceof ExtType1) {
ExtType1 field1 = (ExtType1) value;
// we now know that it's an ExtType1
} else if (value instanceof ExtTypeField2) {
ExtType2 field2 = (ExtType2) value;
// we now know that it's an ExtType2
} // etc...

Categories