Converting a Collection in a generic way in Java - java

I am trying to convert a Collection of objects that implement DomainEntity to a Collection of objects that implement DomainEntityDTO. DomainEntity objects provide a method toDTO() to do the conversion.
Here is my code.
public class EntityCollectionConverter<T extends DomainEntityDTO, Y extends DomainEntity> {
public Collection<T> convert(Collection<Y> collection){
Collection<T> dtoList = new ArrayList<>();
for (DomainEntity domainObject : collection) {
DomainEntityDTO dto = domainObject.toDTO();
dtoList.add(dto); // Compiler: "T cannot be applied to DomainEntityDTO"
}
return dtoList;
}
}
The line dtoList.add(dto); doesn't compile, because "T cannot be applied to DomainEntityDTO'.
The interface DomainEntity looks like this:
public interface DomainEntity {
Long getId();
<T extends DomainEntityDTO> T toDTO();
}
Any idea where I am going wrong?

You need to declare your variable of type T.

Related

Casting to unbound generics in Java

I've got the following java pseudocode
public interface JobData {}
public class JobStatus<T extends JobData> {
public T jobData;
}
public class A implements JobData {}
public class B extends A {}
public class C extends A {}
public class Service {
private Map<Long, JobStatus> jobStatusMap;
public <T extends JobData> List <JobStatus<T>> getJobsByJobDataType(Class<T> clazz)
{
return jobStatusMap.values().stream()
.filter(js -> clazz.isInstance(js.getJobData()))
.map((js) -> (JobStatus<T>) js) // HERE
.collect(Collectors.toCollection(ArrayList::new));
}
}
But I'm having trouble with the line marked "HERE". Essentially, I've got an map of JobStatus objects, each of which has a field, jobData, which is a generic implementing the interface JobData. I want to get all the JobStatus items whose jobData field is a subclass of class of say, class A:
List<JobStatus<A>> jobStatuses = getJobsByJobDataType(A.class);
How do I, I guess at compile-time, cast my JobStatus objects to JobStatus<T>?
I can do a dynamic cast in a number of ways via things like myClass.cast(js), but I'm not sure how to do that if myClass is a generic JobStatus<T> where T is bound or alternatively defined in clazz.
It seems you're attempting to cast elements to a type that is different from the list type. In other words, your return signature is of type List<JobStatus<T>> where JobStatus does not extend JobData, although you're trying to cast each assignable element to the type JobData.
Is this what you want to do?
public interface JobData<T> {
T getData();
}
public interface JobStatus<T extends JobData> {
T getJobData();
}
public class Service {
private Map<Long, JobStatus> jobStatusMap;
public <T extends JobData> List<JobStatus<T>> getJobsByJobDataType(Class<T> clazz) {
return jobStatusMap.values().stream()
.filter(value -> clazz.isAssignableFrom(value.getJobData().getClass()))
.map(value -> (JobStatus<T>) value)
.collect(Collectors.toList());
}
}

Using self-referential generic types in Java

Consider the following Java method:
<T extends List<T>> List<T> getMyList() {
return Collections.emptyList();
}
I can assign its output to a variable with a raw type, like so:
List x = getMyList();
List<List> y = getMyList();
But, I can't think of any way to assign its output to a fully parameterized type. In particular, I can't think of a non-raw, concrete type T that would satisfy List<T> z = getMyList();
Can we create such a T ?
If not, why not?
For context, I created this question while trying to understand how Enums are implemented in Java.
Here's an example of a concrete type that both works and starts to hint at a possible use-case (registration of some sort). The type consists acts like both an instance of some type, and as a container for all instances of that type.
public class WeirdEnum extends AbstractList<WeirdEnum> {
private static List<WeirdEnum> underlyingList = new ArrayList<>();
#Override
public WeirdEnum get(int index) { return underlyingList.get(index); }
#Override
public int size() { return underlyingList.size(); }
static <T extends List<T>> List<T> getAList() {
return Collections.emptyList();
}
public WeirdEnum() {
underlyingList.add(this); // Sufficient for our example but not a good idea due to concurrency concerns.
}
static List<WeirdEnum> foo = WeirdEnum.getAList();
}
Not sure if I fully understand your question, but here's an example:
class Example<T> implements List<Example<T>> {
...
}
...
List<Example<String>> list = getMyList();
Every enum in Java extends from the base-enum-class Enum<T extends Enum<T>>, where T is the actual type of the implementing enum.
When writing SomeClass<T extends SomeClass<T>> you can enforce that the type-parameter is always the implementing class itself.
Let's say you have this interface:
public interface MyInterface<T extends MyInterface<T>> {
T getSelf();
}
And this implementing class:
public class MyClass implements MyInterface<MyClass> {
public MyClass getSelf() {
return this;
}
}
In MyClass it is not possible to use any other type-parameter than MyClass itself.

How do I properly extend this abstract class?

Hi I'm inexperience with Java. I understand the concepts of inheritance but I think the syntax is eluding me. I'm seeking some help to get me started in extending this abstract class:
I need to create a concrete object from it.
What this class should do is take in a type during initialization and store a list of objects of that type. Sort them and then return a list of n top objects when showTopN is called.
I have not started implementing the logic yet.
abstract class Foo<T extends Comparable<T>> {
int n;
Foo(int n){ // constructor; sets object property n
this.n = n;
}
abstract void push(T object); //object method to store a new object in the list
abstract List<T> showTopN(); // object method to return top n entries in the list, sorted.
}
I've tried to extend this into a concrete object this way:
class ConcreteFoo extends Foo {
private List<Foo> fooList;
public void push(Foo object) {
}
#Override
public List<Foo> showTopN() {
return fooList;
}
#Override
public int compareTo(ConcreteFoo other) {
return 0;
}
}
But the compiler is complaining that I have not overridden the push method.
What is wrong?
There are two things going on here. One is the "abstractness" of Foo, but the other is the Generics. You have neglected the generics aspect.
If you know the type of object that your Concrete foo cares about, you can just use that:
class ConcreteFoo extends Foo<SomeKnownClass> {
private List<SomeKnownClass> list = new ArrayList<SomeKnownClass>();
void push(SomeKnownClass skc) {}
List<SomeKnownClass> showTopN() { return list; }
}
Now, if you don't know the type of it, you can still use generics:
class ConcreteFoo<T extends Comparable<T>> extends Foo<T> {
private List<T> list = new ArrayList<T>();
void push(T skc) {}
List<T> showTopN() { return list; }
}
Note that neither Foo nor ConcreteFoo implement Comparable, so you don't need the compareTo method.
The push method specifies that it will accept a T object, which is Foo's generic type, which you haven't declared. If you want Foo to be a List of itself, which I'm not certain that you do, you'd have to declare it as
class ConcreteFoo extends Foo<Foo> {
But I think you need to re-examine your basic principles.
You're conflating a container with the objects that it contains. The class structure that you want is something like:
class Foo implements Comparable<Foo> { ... }
abstract class GenericContainer<T> {
abstract void push(T object); //object method to store a new object in the list
abstract List<T> showTopN(); // object method to return top k entries in the list, sorted.
}
class FooContainer extends GenericContainer<Foo> {
private List<Foo> fooList;
...
}
Your showTopN method can then be something like:
public List<Foo> showTopN() {
return Collections.sort(fooList).subList(0, n);
}

Guava generic for Ordering

I have quite big issue with create generic method for Ordering. At this moment I have this function :
public <T> T orderAscending(Function<?, ? extends Comparable> function, Iterable<? extends LinkedList<?>> sortingList) {
return Ordering.natural().onResultOf(function).sortedCopy(sortingList);
}
First parameter of this function is created in this way :
public static Function<ParkingWebApiDTO, Date> getSortActiveParkingsByStartDate() {
Function<ParkingWebApiDTO, Date> getStartDateFunction = new Function<ParkingWebApiDTO, Date>() {
#Override
public Date apply(ParkingWebApiDTO parkingWebApiDTO) {
return parkingWebApiDTO.getStartDate();
}
};
return getStartDateFunction;
}
and the second one is LinkedList with some custom object in it (List<MyObject> test = new LinkedList<MyObject>()).
Please someone help me to fix this generic method orderAscending. Much appreciated for help.
I guess you meant to create List (sorted by start date) from Iterable of your DTOs (I assume you don't want iterable of lists of DTOs).
So let's say your DTO looks like this:
interface ParkingWebApiDTO { // could be simple class, etc.
Date getStartDate();
// ...and more methods here
}
you have input list:
LinkedList<? extends ParkingWebApiDTO> iterable = Lists.newLinkedList();
and function which retrieves start date from DTO:
Function<ParkingWebApiDTO, Date> function = new Function<ParkingWebApiDTO, Date>() {
#Override
public Date apply(ParkingWebApiDTO dto) {
return dto.getStartDate();
}
};
you expect output like this:
List<? extends ParkingWebApiDTO> result = orderAscending(function, iterable);
which can be achieved with following orderAscending imlementation:
public static <X, T extends Comparable<T>> List<? extends X> orderAscending(
Function<X, T> function, Iterable<? extends X> sortingList) {
return Ordering.natural().onResultOf(function).sortedCopy(sortingList);
}
You need to declare both from and to types as generic types if you want to have "universal" method.
Another thing is if you really need to have such generic name, because using Ordering.natural().onResultOf(function).sortedCopy(list) is perfectly fine and having orderAscending is IMO overkill (you'll end with plenty of methods like this one).

Basic Java type casting issue

I've an interface called DataHandler with the following declaration among others:
public List<Object> getIt();
while the ProjectSet class implements this interface.
This class handles Project objects and the implementation of the getIt() method for the ProjectSet class should return a list of Projects
like:
List<Project>
How to do this in Java?
Regards,
Gerard
You can take advantage of Generics in Java by declaring the method in your interface as:
public interface DataHandler<T> {
public List<T> getIt();
}
This means that the DataHandler interface is tied to a specific, unknown type T. The getIt() method returns a List of that class T. In other words, it could be seen as DataHandler will handle objects of class T.
And then provide your implementation, specifying that ProjectSet will be a DataHandler handling Project objects:
public class ProjectSet implements DataHandler<Project> {
public List<Project> getIt() { }
}
You might find this lesson of the Java Tutorials useful.
public List<T> getIt();
in your interface and
Like this
public interface MyInterface<T> {
public List<T> getIt();
}
then implement it with
implements MyInterface<Project>
You cannot do that in java this way.
My solution would be to have the data handler be generic
public interface DataHandler<T> {
public List<T> getIt();
}
then you can do
public ProjectSet implements DataHandler<Project> {
public List<Project> getIt() { ... }
}
You have 3 options:
Change the interface to be Generic:
interface DataHandler<T> {
List<T> getIt();
}
class ProjectSet implements DataHandle<Project> {
List<Project> getIt() {
...
}
}
This is hard because you need to change the interface, and refactorize all classes that implements DataHandler. This some thimes is not a option.
Cast a List
The type information of the list is gone in runtime, for this, all List type are equals in runtime, and equal to Object, so you can do this:
class ProjectSet implements DataHandle {
List<Object> getIt() {
...
return (List) projectList;
}
}
This is Ugly, but works!, you can add a #SuppressWarnings("unchecked") to skip the warnings.
Create a List of Objects
class ProjectSet implements DataHandle {
List<Object> getIt() {
List<Object> retObject = ... ;
for (Project p : getProjects()) {
retObject.add(p);
}
return retObject;
}
}
This is only ugly!.

Categories

Resources