Java Generics, how to avoid unchecked assignment warning when using class hierarchy? - java

I want to use a method using generic parameters and returning generic result on a class hierarchy.
edit: no SupressWarnings("unchecked") answer allowed :-)
Here is a sample code illustrating my problem:
import java.util.*;
public class GenericQuestion {
interface Function<F, R> {R apply(F data);}
static class Fruit {int id; String name; Fruit(int id, String name) {
this.id = id; this.name = name;}
}
static class Apple extends Fruit {
Apple(int id, String type) { super(id, type); }
}
static class Pear extends Fruit {
Pear(int id, String type) { super(id, type); }
}
public static void main(String[] args) {
List<Apple> apples = Arrays.asList(
new Apple(1,"Green"), new Apple(2,"Red")
);
List<Pear> pears = Arrays.asList(
new Pear(1,"Green"), new Pear(2,"Red")
);
Function fruitID = new Function<Fruit, Integer>() {
public Integer apply(Fruit data) {return data.id;}
};
Map<Integer, Apple> appleMap = mapValues(apples, fruitID);
Map<Integer, Pear> pearMap = mapValues(pears, fruitID);
}
public static <K,V> Map<K,V> mapValues(
List<V> values, Function<V,K> function) {
Map<K,V> map = new HashMap<K,V>();
for (V v : values) {
map.put(function.apply(v), v);
}
return map;
}
}
How to remove the generic exception from these calls:
Map<Integer, Apple> appleMap = mapValues(apples, fruitID);
Map<Integer, Pear> pearMap = mapValues(pears, fruitID);
Bonus question: how to remove the compilation error if I declare the fruitId Function this way:
Function<Fruit, Integer> fruitID = new Function<Fruit, Integer>() {public Integer apply(Fruit data) {return data.id;}};
I'm very confused about generics when it is dealing with hierarchy. Any pointer to a good resource about the usage of and will be greatly appreciated.

2 small changes:
public static void main(final String[] args){
// ... snip
// change nr 1: use a generic declaration
final Function<Fruit, Integer> fruitID =
new Function<Fruit, Integer>(){
#Override
public Integer apply(final Fruit data){
return data.id;
}
};
// ... snip
}
public static <K, V> Map<K, V> mapValues(final List<V> values,
// change nr. 2: use <? super V> instead of <V>
final Function<? super V, K> function){
// ... snip
}
For reference, read this:
The get-put principle

Related

Generic specification in chained method call

public class Foo<T> {
public static <T> Foo<T> newFoo() {
return new Foo<>();
}
public Bar<T, T> toBar() {
return new Bar<>(this, new ArrayList<T>());
}
}
public class Bar<S, T> {
public Bar(Foo<T> Foo, List<S> list) {
}
public static void main(String[] args) {
Foo<Integer> newFoo = Foo.newFoo();
Bar<Integer, Integer> s = newFoo.toBar();
Bar<Integer, Integer> s2 = Foo.newFoo().toBar();
}
}
The first two lines of the main method work fine. The last line (Foo.newFoo().toBar()) gives me an error: Type mismatch: cannot convert from Bar<Object,Object> to Bar<Integer,Integer>. Is there a way to this in one line without getting an error? Casting to Bar<Integer, Integer> doesn't work.
More out of curiosity than necessity...
This works:
Bar<Integer, Integer> s2 = Foo.<Integer>newFoo().toBar();

Using generics for a class how can I convert the values from one type to another?

I built a simple document store, there are entities that have fields of different types, I have a Float, Int and String type. The entity contains an array list of values, if someone updates the schema of the entity I would like to be able to try to convert the values to the new type.
public interface FieldType<T> {
ArrayList<T> values;
}
public class FloatField implements FieldType<Float> {
}
public class StringField implements FieldType<String> {
}
I have thought about using a abstract class with methods as below
public abstract class Field<T> implements FieldType<T> {
abstract public <T> castFromString(String value);
abstract public <T> castFromFloat(Float value);
abstract public <T> castFromInt(Int value);
}
public class FloatField extends Field<Float> {
#override
public <Float> castFromString(String value){
Float castValue = null;
try {
castValue = Float.parseFloat(value);
} catch(Exception e){
}
return castValue;
}
}
I did not really like this solution as I would have to add a new abstract method each time I added an extra type to the system.
Any ideas how I could implement this better?
Maybe you could use the Function<T, R> interface?
public abstract class Field<T> implements FieldType<T> {
...
public <F> T convert(F value, Function<F, T> converter) {
try {
return converter.apply(value);
} catch(Exception e) {
return null;
}
}
...
}
And then specify the converter using a lambda expression or a method reference:
field.convert("1234", BigDecimal::new); //with a method reference
field.convert("1234", s -> new BigDecimal(s)) //with a lambda
This would replace all of your convertXXX methods by one since the return type is inferred from the passed Function.
EDIT:
If you want automatic converting, you would of course have to hard-code these since you wouldn't want to write conversion methods for all 4240 classes in the Java API. This gets messy, though. Maybe something like this in a static helper class or in FieldType itself?
public class WhereverYouWantThis {
private static HashMap<Class<?>, HashMap<Class<?>, Function<?, ?>>> converters = new HashMap<>();
static {
putConverter(String.class, Float.class, Float::parseFloat);
}
private static <T, R> void putConverter(Class<T> t, Class<R> r, Function<T, R> func) {
HashMap<Class<?>, Function<?, ?>> map = converters.get(t);
if(map == null) converters.put(t, map = new HashMap<>());
map.put(r, func);
}
public static <T, R> Function<T, R> getConverter(Class<T> t, Class<R> r) {
HashMap<Class<?>, Function<?, ?>> map = converters.get(t);
if(map == null) return null;
#SuppressWarnings("unchecked")
Function<T, R> func = (Function<T, R>) map.get(r);
return func;
}
public static <T, R> R convert(T o, Class<R> to) {
#SuppressWarnings("unchecked")
Function<T, R> func = (Function<T, R>) getConverter(o.getClass(), to);
return func == null ? null : func.apply(o);
}
}
I don't think you need generics for this. Instead, just try to create a Float from the input String and return null if there be a problem:
public Float castFromString(String value) {
Float castValue = null;
try {
castValue = Float.parseFloat(value);
} catch(Exception e){
// log here
}
return castValue;
}
The reason I don't think generics are needed is that the types involved in the conversion are named/known in your helper methods.

How Can I create method which use Java generics put the maps key to list?

public <T> List<T> map2list(Map<T, T> map){
List<T> list = new ArrayList<T>(map.keySet());
return list;
}
My Method like this... But it does not work.
Maybe your map is empty, because the example below works:
public class Utils {
public <T, K> List<T> map2list(Map<T, K> map) {
List<T> list = new ArrayList<T>(map.keySet());
return list;
}
/**
* #param args
*/
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("test1", 1);
map.put("test2", 2);
map.put("test3", 3);
Utils t = new Utils();
List<String> result = t.map2list(map);
for (String key : result) {
System.out.println(key);
}
}
}
printing the following:
test2
test3
test1
If your map in argument is of String as key & Integer as value, try following method,
public static <T, L> List<T> map2list (Map<T, L> map) {
List<T> list = new ArrayList<T>(map.keySet());
return list;
}
<T> define only one type for the runtime type-aguments of your map. So if you have different types of arguments for the generics of your map, you can change it like this by defining two generic type T and for example K:
public static <T,K> List<T> map2list(Map<T, K> map){
List<T> list = new ArrayList<T>(map.keySet());
return list;
}
And it will work.
Also this situation supports that if you want to pass Map<String,String> or generally Map<T,T> too.
Hope this would help.

Getting key from object for Map using object and interface

I have a Table class that implements a ForwardingMultimap of a certain type of object. I was wondering if it was over-doing it to create an interface that extracted the key from the object so it wouldn't be annoying for the caller to handle "Entry" objects when they call "values". Or would it just be better to have the caller put the object and key in themselves? If this is okay, would creating a separate class to handle each key like below be better, or should the caller implement it themselves ?
public class CustomObject {
public String propertyOne;
public int propertyTwo;
}
public interface ITableAggKey {
Object getKey(CustomObject customObj);
}
public class Table extends ForwardingMultimap<Object, CustomObject> {
Multimap m_map;
public Table(ITableAggKey aggKey){
m_map = HashMultimap.create();
m_aggKey = aggKey;
}
public boolean put(CustomObject obj) {
m_map.put(m_aggKey.getKey(obj), obj);
}
}
public class CustomObjectAggKeys {
public static final aggKeyOne = new ITableAggKey(){
#Overide
public Object getKey(CustomObject obj){
return obj.propertyOne;
}
};
public static final aggKeyOne = new ITableAggKey(){
#Overide
public Object getKey(CustomObject obj){
return obj.propertyTwo;
}
};
}
public class Table<K, T> extends ForwardingMultimap<K, T> {
Multimap<K, T> m_map;
Function<T, K> m_aggKey;
public Table(Function<T, K> aggKey){
m_map = HashMultimap.create();
m_aggKey = aggKey;
}
public boolean put(T obj) {
m_map.put(m_aggKey.apply(obj), obj);
}
}
public static void main(String[] args) {
Table<String, CustomObject> IndexOne = new Table<>(x -> x.propertyOne);
Table<Integer, CustomObject> IndexTwo = new Table<>(x -> x.propertyTwo);
}
If you cannot use Java8. Add Function interface.
public interface Function<T, K> {
K apply(T arg);
}
And
Table<String, CustomObject> indexOne = new Table<>(new Function<CustomObject, String>() {
#Override public String apply(CustomObject obj) {
return obj.propertyOne;
}
});

Java - generics & wildcards & interface versus implementation

I have a question about Java generics. Say I have the following interface:
public static class Something<T> {
public void set(T t) {
}
}
public static interface Manager<T> {
public void add(final String key, final Something<T> o);
public Something<T> get(final String key);
}
An example of usage:
final Manager<Number> m = ...;
m.add("key", new Something<Number>());
m.get("key").set(new Integer(5));
I would also like to be able to add Something<Integer>, Something<Double>, ... to the a Manager<Number>. I would say I have to change the signature of the add-function:
public static interface Manager<T> {
public void add(final String key, final Something<? extends T> o);
public Something<T> get(final String key);
}
final Manager<Number> m = ...;
m.add("key", new Something<Integer>());
m.get("key").set(new Integer(5));
So far, so good. Let's look at a possible implementation of the manager:
public static class ManagerImplementation<T> implements Manager<T> {
protected HashMap<String, Something<T>> map = new HashMap<String, Something<T>>();
public void add(final String key, final Something<? extends T> o) {
map.put(key, o); // <--- here
}
public Something<T> get(final String key) {
return map.get(key);
}
}
This fails, since you cannot add a Something<? extends T> to a Map<X, Something<T>>. So let's change this:
public static class ManagerImplementation<T> implements Manager<T> {
protected HashMap<String, Something<? extends T>> map = new HashMap<String, Something<? extends T>>();
public void add(final String key, final Something<? extends T> o) {
map.put(key, o);
}
public Something<T> get(final String key) {
return map.get(key); // <--- here
}
}
This fails since map.get(key) returns Something<? extends T> while the get-function is required to return Something<T>, as defined in the interface.
What is the common approach to solve this?
Thanks!
Inside your class you are always using Something<? extends T>, thus in your public get method you must convert the inside world to the outside world format. E.g. you can simply cast the result of map.get(key) to Something<T>:
return (Something<T>) map.get(key); // <--- here

Categories