Guava generic for Ordering - java

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).

Related

Do these two Java generic methods accept the same data types?

I'm new to Java and I'm trying to learn about generics. I tried to implement a simple version of binarySearch() method that is also found in the Collections class. I looked up the method signature and it's something like this:
public static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key) {
// definition
}
I was wondering if the method above still accepts the same data types if you were to change the method definition to this:
public static <T extends Comparable<? super T>> int binarySearch(List<T> list, T key) {
// definition
}
If not, what are the differences between the two? Thank you!
Consider these classes:
class A extends Comparable<A> { /* ... */ }
class B extends A { /* ... */ }
Now define a key and a list with these types:
A key = new B();
List<B> list = List.of(key);
You can invoke the first form with these arguments, but not the second.
For example:
static class NonComparable {
}
static class MyComparable implements Comparable<NonComparable> {
#Override
public int compareTo(NonComparable o) {
return 0; // irrelevant for the example
}
}
And then declare the parameters:
List<MyComparable> list = Arrays.asList(new MyComparable());
NonComparable nonComparable = new NonComparable();
binarySearch(list, nonComparable);
One of your method definitions allows an invocation, the other does not.

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.

Number.valueOf() implementation for Java generics

I have been using a Collection of number values and have implemented some related functionality (mapping x->y values, etc). So far I have made use of generics to allow any subclass of Number in the Collection.
In this particular class I keep running into the problem that there is no easy way to cast to the generic. The usual methods like Double.valueOf() cannot be invoked because Number does not provide such a method.
Is there a good way around this?
I have found this post and thought that would solve it, but I cannot pass the Class.class parameter to it.
public class myList<T extends Number> extends Collection<T> {
#Override
public boolean add(T value){
// this is no problem
}
// What I want to do:
public boolean add(double value){
return this.add(T.valueOf(value));
}
// Using the example I found:
public void add(double value){
return this.add( (T) Ideone.parse(value, T.class) ); // no such option
}
}
Thanks in advance.
There's no way for the myList class to be able to convert double to T, because T is unknown.
One way you can solve this is to let the caller provide a function that converts from double to T. Here's an example:
public class myList<T extends Number> implements Collection<T> {
private DoubleFunction<T> fromDoubleFunction;
public myList(DoubleFunction<T> function) {
this.fromDoubleFunction = function;
}
public boolean add(double value) {
return this.add(this.fromDoubleFunction.apply(value));
}
//rest of code
}
That can then be used in this way:
myList<Integer> intList = new myList(d -> Double.valueOf(d).intValue());
Provide a DoubleFunction<T> to your class as a constructor parameter.
public class myList<T extends Number> extends Collection<T> {
private final DoubleFunction<T> theDoubleFn;
public myList(DoubleFunction<T> theDoubleFn) {
this.theDoubleFn = theDoubleFn;
}
// ...
Then invoke:
return this.add(theDoubleFn.apply(value));
in the method.

TreeMap with Classes as Key

I am trying to program a kind of registry for objects of different classes.
I have the following:
public interface DbObject{
void setId(long id);
Long getId();
}
A prototypic class implementing this interface would be the following:
public class BasicDbObject implements DbObject{
private long id=null;
void setId(long id){
this.id=id;
}
Long getId(){
return id;
}
}
I want to build various different Implementations of this Interface.
And I want to be able to have a Map object, that maps from each implementing class to a Map of instances.
Something like this:
Map <Class<C implements DbObject> , Map<Long, C>> registry = new TreeMap/HashMap/SomeOtherKindOfMap (...)
I know I could do something like
Map <String,Map<Long,DbObjects>> registry = new ...
But this way I would have to write some more code for determining names, comparing classes and so on. Is there an easier way to accomplish this?
So what I want to know: is it possible to have class objects as keys in a tree map?
What would be the syntax to declare a map object, that maps from implementing classes C to a map objects each mapping from a long object (the id) to instances of C?
I want to be able to do requests like the following:
BasicObject bo = registry.get(BasicObject.class).get(42);
assuing id did
BasicObject bo=new BasicObject(...);
innerMap = new SomeMap<Long,BasicObject>();
innerMap.put(42,bo);
registry.put(BasicObject.class,innerMap);
before.
Please tell me, if this still is not clear, I have difficulties to explain, since english is not my mother tongue.
Thank you in advance.
Edit:
It turns out, i can do something very close to what I want, when defining a generic class around the map:
public class ObjectRegistry <T extends DbObject>{
private HashMap<Class<T>, TreeMap<Long,T>> registry=null;
ObjectRegistry(){
registry=new HashMap<Class<T>, TreeMap<Long,T>>();
}
public void register(T dbObject){
TreeMap<Long, T> map = registry.get(dbObject.getClass());
if (map==null){
map=new TreeMap<Long,T>();
registry.put((Class<T>) dbObject.getClass(),map);
}
map.put(dbObject.getId(),dbObject);
}
public <T extends DbObject>T get(Class<T> objectClass,long id){
TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(objectClass);
if (map != null){
return map.get(id);
}
return null;
}
public TreeMap<Long,T> getAll(Class<T> dbObjectClass) {
return registry.get(dbObjectClass);
}
}
I use a TreeMap for the inner mappings since I want to easily return Class instances sorted by id.
So the refined question is:
Is there a way to do this, without the <T extends DbObject> clause in the Class head?
Edit 2:
Thinking through it again, it turns out that John's answer is exactly the solution to this.
Here is my final code:
HashMap<Class<? extends DbObject>, TreeMap<Long, ? extends DbObject>> registry = null;
public <T extends DbObject> T get(Class<T> clazz, long id) {
TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(clazz);
if (map != null) {
return map.get(id);
}
return null;
}
public <T extends DbObject> void register(T dbObject) {
TreeMap<Long, T> map = (TreeMap<Long, T>) registry.get(dbObject.getClass());
if (map == null) {
map = new TreeMap<Long, T>();
registry.put((Class<T>) dbObject.getClass(), map);
}
map.put(dbObject.getId(), dbObject);
}
public <T extends DbObject> TreeMap<Long, T> getAll(Class<T> dbObjectClass) {
return (TreeMap<Long, T>) registry.get(dbObjectClass);
}
It does not need the <T extends DbObject> clause in the Class head.
So what I want to know: is it possible to have class objects as keys in a tree map?
TreeMap depends on there being a total order over the key space, as established by the key type having a natural order (by implementing Comparable) or by a separate Comparator object that you provide. Classes do not have a natural order. It is conceivable that you could write a suitable Comparator, but that seems very contrived to me.
But why do you specifically need a TreeMap? You didn't describe any requirement that would not be at least as well addressed by any other kind of Map. In particular, I almost always find HashMap to be a better choice, and I don't see any reason why it would be unsuitable in this one. It can certainly have objects of type Class as keys.
Moreover, if indeed you don't need any particular implementation, then you are best off declaring the type simply as a Map. That way you can actually provide any Map implementation, and even change which one you do provide if you ever discover a reason to do so.
What would be the syntax to declare a map object, that maps from implementing classes C to a map objects each mapping from a long object (the id) to instances of C?
You ask that the constraints on the type of each value be dependent on the type of the associated key, but there is no way to declare a type that enforces such a relationship. Whether a particular key or a particular value is appropriate for the Map is a function of the type of the map alone, not of each others' type.
You can write generic methods around access to your map that provide the appearance of what you want, but the data retrieval methods will need to cast. For example:
Map<Class<? extends DbObject>, Map<Long, ? extends DbObject>> registry = /*...*/;
<T extends DbObject> Map<Long, T> getRegistryMap(Class<T> clazz) {
return (Map<Long, T>) registry.get(clazz);
}
<T extends DbObject> T get(Class<T> clazz, Long id) {
Map<Long, T> map = getRegistryMap(clazz);
return (map == null) ? null : map.get(id);
}
<T extends DbObject> T put(Class<T> clazz, Long id, T obj) {
Map<Long, T> map = getRegistryMap(clazz);
if (map == null) {
map = new HashMap<>();
registry.put(clazz, map);
}
return map.put(id, obj);
}
Updated to add:
So the refined question is: Is there a way to do this, without the <T extends DbObject> clause in the Class head?
Yes, what I already wrote. Just slap a plain class declaration around it. You do not need a generic class to have generic methods. In fact, the two are orthogonal. Regular methods of a generic class can use that class's type parameters. That does not make them generic methods. A method is generic if it declares its own type parameter(s), as mine above do. Your get() method also does that, and it is important to understand that the type parameter <T> you declare explicitly in the method signature shadows the class's type parameter of the same name: it is a different T.

In a Transformer, how to specify that the types fo the classes being transformed are of the same type?

I'm having a very simple yet confuse question at the same time.
In a Transformer, is there a way to specify that the types of the classes being transformed are the same type?
To make it clear, I'll share the code:
Transformer<Set<?>, List<?>> transformer = new SetToListTransformer();
Is there a way for me to specify that the Set and the List are of the same type?
Also when writing the transformer I did this, and I assume it serves no purpose:
private static class SetToListTransformer implements Transformer<Set<?>, List<?>> {
#Override
public List<?> transform(final Set<?> input) {
return this.doTransform(input);
}
public <T> List<T> doTransform(final Set<T> input) {
...
}
}
The thing is, I cannot type the SetToListTransformer since I do not really care about what types are inside, I just care that they are the same type.
Any help would be appreciated!
PS: I'm not really transforming a Set into a List, I'm using other types, I just used them to clarify the code :)
Try to bind both wildcards to the same type paramter, like this:
class SetToListTransformer<E> implements Transformer<Set<E>, List<E>> {
#Override
public List<E> transform(Set<E> from) {
...
}
}
Make your class generic:
private static class SetToListTransformer <T> implements Transformer<Set<T>, List<T>> {
#Override
public List<T> transform(Set<T> input) {
return this.doTransform(input);
}
public List<T> doTransform(Set<T> input) {
...
}
}
Note, however, that this implementation is quite strict with types. You wont be able to use a SetToListTransformer<Number> to convert from Set<Integer> to List<Number>, although Integer IS a Number.
There's no way to enforce the desired constraint on your transform implementation, since there is no way to impose any relationship between generic wildcards. Each of the two ? in your SetToListTransformer declaration are doomed to each mean some unknown type with no way to bound them to each other.
As others pointed out, the easiest solution is to make SetToListTransformer generic. For example:
class SetToListTransformer<T> implements Transformer<Set<? extends T>, List<T>> {
#Override
public List<T> transform(final Set<? extends T> input) {
final List<T> output = new ArrayList<T>(input.size());
output.addAll(input);
return output;
}
}
Of course this requires you to instantiate transformers with specific type arguments. This should be fine as long as SetToListTransformer is cheap. But, you indicated you just want to use one instance. Here's how to do that:
class MyTransformers {
// There is no reason to expose SetToListTransformer now.
// Keep it here as an anonymous class.
private static final Transformer<Set<?>, List<?>> FROM_SET_TO_LIST =
new Transformer<Set<?>, List<?>>() {
#Override
public List<?> transform(final Set<?> input) {
return doTransform(input);
}
private <T> List<T> doTransform(final Set<T> input) {
final List<T> output = new ArrayList<T>(input.size());
output.addAll(input);
return output;
}
};
private MyTransformers() { }
public static <T> Transformer<Set<? extends T>, List<T>> fromSetToList() {
#SuppressWarnings("unchecked")//this is okay for any T because the impl is stateless
final Transformer<Set<? extends T>, List<T>> withNarrowedTypes =
(Transformer<Set<? extends T>, List<T>>)(Transformer<?, ?>)FROM_SET_TO_LIST;
return withNarrowedTypes;
}
}
Here's a usage example:
Set<Integer> intSet = new HashSet<Integer>();
intSet.add(42);
intSet.add(1337);
List<Number> numList = MyTransformers.<Number>fromSetToList().transform(intSet);
You can't express that constraint with the Transformer interface. You may create a subtype that imposes additional constraints, and use the subtype where Transformer was used.
interface StricterTransformer extends Transformer<Set<?>, List<?>>
public <T> List<T> transform2(Set<T> input) ;
/** javadoc additional contract: must behave as transform2(input) */
public List<?> transform(Set<?> input);
// in java8 we can give a "default" impl for this interface method
// that simply calls transform2(), so subclasses don't have to impl
// the transform() method, which is just boiler plate code.

Categories

Resources