I´m trying to use generic in a method where I deserializing a json into pojo so it could return whatever object type.
Here my code:
private Bla(List<A> as, List<B> bs)
{
this.as = as;
this.bs = bs;
}
public static Bla from(JsonObject json)
{
return new Bla(Bla.<A>load(json, As), Bla.<B>load(json, Bs));
}
private static <T> List<T> load(JsonObject jsonObject, String param)
{
return jsonObject.getJsonArray(param).stream()
.map(Bla::getItem)
.collect(Collectors.toList());
}
private static <T> T getItem(Object json)
{
try {
return mapper.readValue(json.toString(), new TypeReference<T>() {
});
} catch (IOException e) {
throw new RuntimeException("Error parsing json items", e);
}
}
The problem is that .collect(Collectors.toList());
seems not compile cause cannot resolve the instance type.
The compilation error is:
Error:(43, 25) java: incompatible types: inference variable T has incompatible bounds equality constraints: T lower bounds: java.lang.Object
To avoid confusion in my example A and B are Pojos
Regards.
For this particular test, streams are about twice as slow as collections, and parallelism doesn't help (or either I'm using it the wrong way?).
We can use Stream collect() function to perform a mutable reduction operation and concatenate the list elements. The supplier function is returning a new StringBuilder object in every call. The accumulator function is appending the list string element to the StringBuilder instance.
collect() Method. Stream. collect() is one of the Java 8's Stream API's terminal methods. It allows us to perform mutable fold operations (repackaging elements to some data structures and applying some additional logic, concatenating them, etc.) on data elements held in a Stream instance.
Let's examine this method:
private static <T> List<T> load(JsonObject jsonObject, String param)
{
return jsonObject.getJsonArray(param).stream()
.map(Bla::getItem)
.collect(Collectors.toList());
}
The type of the last step, Collectors.toList()
must be List<T>
, but to get it the type of the previous step, Bla::getItem
must be inferred as T getItem
. Since getItem
is a generic method, this needs a complex pattern of type constraint propagation which is apparently more than Java's type inference will handle. To solve this, help the compiler with a hint:
.map(Bla::<T>getItem)
(credit for this syntactic variant goes to user Nándor Előd Fekete).
A second issue is your getItem
method:
private static <T> T getItem(Object json)
{
return mapper.readValue(json.toString(), new TypeReference<T>() {};
}
Using TypeReference
here doesn't help because T
is not a concrete type. It will remain non-reified in the anonymous class that the compiler creates here, therefore Jackson will get no helpful hint from it. You can just use a simpler readValue
signature that doesn't take the TypeReference
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With