This question is in response to another question by opensas: building a generic initializer function in java
From his question it became clear that he needs to convert from any data type T1 to another type T2. When I say "data type" here, I mean types limited to those commonly used to represent raw data: Integer, String, Date, etc. For the purpose of this question we can consider primitives to be boxed.
I'm wondering if there is any API that supports conversion between types where both the input and output are generalized to a set of supported data types. I had a look at Apache Commons' beanutils.converters package, but there's a separate converter class for each known input. I'm looking for any functionality that implements something like the following signature:
static <IN, OUT> OUT convert(IN value, Class<OUT> targetType);
or else
static <IN, OUT> OUT convert(IN value, OUT defaultValue);
It really wouldn't be too hard to implement this kind of mapping oneself, either using a bunch of else if blocks pointing to the various Commons Converters, or else a Map<Class<?>, Converter> for the same purpose. But I'm wondering if this kind of functionality is supported somewhere.
Also, if this winds up being a duplicate I apologize. I tried finding similar questions and was surprised when I found none matching this situation.
EDIT: so an example of this code in action would be:
Integer i = GenericConverter.convert("123", Integer.class); //returns 123
Date d = GenericConverter.convert(1313381772316L, Date.class); //returns today's date
Boolean b = GenericConverter.convert(0, Boolean.class); //returns false
Long l = GenericConverter.convert("asdf", Long.class); //RuntimeException
UPDATE: The BalusC code I linked falls close to the mark, and Bohemian's answer is a nice lightweight solution (although it doesn't work for Boolean conversions). He's also right that Dates should be probably be handled separately if we want to generalize conversion of these other data types. I'm still hoping for additional answers though - especially if there is more of a hands-off API available somewhere.
I am not aware of any library, however the code is just one line.
Apart from Date, all boxed primitives have a String construtor, so this method does the trick:
public static <I, O> O convert(I input, Class<O> outputClass) throws Exception {
return input == null ? null : outputClass.getConstructor(String.class).newInstance(input.toString());
}
To cater for Dates, you could use instanceof within the method, but I would recommend a separate method, since converting dates is a format- and context-sensitive thing (eg String-->Date parses and uses which format?, Long-->Date sets the time).
I have deliberately left error/special handling to the reader as an exercise.
In JDK 8 this can be easily implemented with the new java.util.functions.Mapper interface and a lambda expression.
Mapper<String,Integer> atoi = s -> Integer.valueOf(s);
Integer r = atoi.map("10");
Using method references it can be even simpler:
Mapper<String, Integer> atoi = Integer::new;
Integer r = atoi.map("10");
Or things like:
List<Long> dates = asList(1344754620310L,1344754854877L);
List<Date> asDates = dates.map(Date::new).into(new ArrayList<Date>());
Or cool conversions like:
List<Integer> myInts = "5,4,3,2,1,0,6,7,8,9"
.splitAsStream(",")
.map(Integer::new)
.into(new ArrayList<Integer>());
In the current implementation of the JDK8 API, a few default mappers have been defined (i.e. LongMapper, IntMapper, DoubleMapper) and there's a utility class called Mappers that defines some others like a string mapper, and identity mapper, a constant mapper, etc.
I am not sure if this is what you are after, but certainly it must be a nice way to implement it.
Cases like the one you suggest for:
static <IN, OUT> OUT convert(IN value, Class<OUT> targetType);
Can be implemented with the Mappers utility class:
Mapper<String, Integer> atoi = Mappers.instantiate(String.class, Integer.class);
Integer r = atoi.map("10");
And your signature:
static <IN, OUT> OUT convert(IN value, OUT default);
Could be implemented with something like:
Mapper<String, Integer> atoi = chain(substitute(null, "0"), Integer::new);
Integer r = atoi.map(null); //produces 0
As such, a code like this...
List<String> data = asList("0", null, "2", null, "4", null, "6");
List<Integer> myInts = data.map(chain(substitute(null, "0"), Integer::new)).into(new ArrayList<Integer>());
System.out.println(myInts);
Would yield: [0, 0, 2, 0, 4, 0, 6]
If you are using Spring Framework (spring-core), you can use class
org.springframework.core.convert.support.DefaultConversionService
Default constructor adds many types converter and you can add your own by implementing Converter interface and call addConverter(Converter). There is also nice unit test showing some conversion combinations.
I found something by BalusC that looks close to what I'm asking for: http://balusc.blogspot.com/2007/08/generic-object-converter.html
Unfortunately nothing involving Date conversion is supported, but as the comments indicate, more conversion methods are easily added. His class is essentially a nice little framework that uses reflection to gather up all conversion methods at runtime and put them in a HashMap<String, Method> where the key String is a unique id for that input-output combination.
Still looking for other suggestions! Particularly for an API that would be more hands off than this code I linked to.
Take a look at Variance, which allows you to set up a type conversion context with various converters registered and then move values into and out of a Variant type with type conversion handled by the context.
Variant aVariant = Variant.of("1.2345");
double aDouble = aVariant.doubleValue();
int anInt = Variant.of("12").intValue();
String aString = Variant.of(12.0).toString();
Date aDate = Variant.of("2012-04-06").as(Date.class);
String anIsoFormattedDate = Variant.of(aDate).in(isoDateFormattingContext).toString()
Converters are just Guava Functions from one type to another, and you can register your own, overriding existing conversions where desired.
Related
I have a method that needs to operate on a very general message. It receives an Object. I can determine if the Object is an array with:
obj.getClass().isArray()
but after that I need to find what the type of the array elements are.
My code will ultimately be passing data one element at a time to a system that will be re-building it's own data structure and I need to tell it what type it should be using. E.g. imagine a JSON or XML message to something else and I need to tell that service how it should treat the data that was given to it in the message:
long [] data = { 42 };
processObject(data);
void processObject(Object obj) { ... }
will produce something like:
<msg>
<value>42</value>
<type>LONG</type>
</msg>
There is only one int type in all of java, which therefore means there is only one int[] type. Thus, it is as simple as:
if (obj instanceof int[]) {
doSomethingWithIntArray((int[]) obj);
}
Or if you somehow want it in terms of class: if (obj.getClass() == int[].class) {.
If you want an enum, it's a simple matter of 8 if/elseifs. You can also make: Map<Class<?>, EnumType>, loading it up with a static initializer / using Map.of`:
private static final Map<Class<?>, EnumType> TYPES = Map.of(
int[].class, EnumType.INT,
byte[].class, EnumType.BYTE,
....);
and then you can call EnumType primitiveType = TYPES.get(obj.getClass()); which returns null if it's not a primitive array, and the EnumType you wanted if it is.
The if/elseif seems less efficient (8 steps, instead of the 1 step that TYPES.get would do), but is probably an order of magnitude or two faster. Far less overhead, CPUs pipeline, 8 chained ifs is nothing.
You want 'most efficient' and then talk about JSON and XML. Two formats that are quite, to notoriously, inefficient.
If you want to improve throughput and the like, you're barking up the wrong tree here. Making the java mode more efficient is going to speed up the process by at most 0.00000001%. Use a protocol designed for fast throughput (such as protobuf or something else binary oriented) if efficiency is what you're after.
I'm a newbie in Hadoop world. I want to know what are the types of <K,V> in InputSampler<K,V> or InputSampler.Sampler<K,V>? This is equal to key and value coming out from Mapper? The examples on
Internet don't use them. For example this link just instantiate it without generics:
InputSampler.Sampler sampler = new InputSampler.RandomSampler(pcnt, numSamples, maxSplits);
Yes, when looking at the code, K denotes the type of the key, V denotes the value type. The real Writable type depends on what kind of input you want to sample, in that sense- yes it is similar to what you would use in a Mapper.
RecordReader<K,V> reader = inf.createRecordReader(splits.get(i), samplingContext);
reader.initialize(splits.get(i), samplingContext);
while (reader.nextKeyValue()) {
samples.add(ReflectionUtils.copy(job.getConfiguration(),
reader.getCurrentKey(), null));
}
Suppose I have a class that has a lot of different fields. This class is a DTO and for testing purposes, I do not care about actual values, just it exists. Is there any tool that can traverse through all fields and set primitives, 0 for Number (0.0 for Float, Double, 0 for Integer, 0L for Long, but not null as default), something like "test" for String?
Also, I want that tool to populate Collections (List, Set, Map).
Just a small googling provide this results:
EasyRandom simple to use modern java solution, formerly known as Random beans
EasyRandom for Java 6, formerly known as JPopulator.
PODAM with a
tutorial
else you can use reflection to populate:
primitive/wrapper with default value
string with rendom value
Collection<T>(set,list) with random size and re-using code to
populate <T>
and so on.
Else XML binding (with jaxb or other technology) can be an option but needs to prepare xml with data in advance.
Except frameworks all other solutions have two big issues: needs to be written and a lot of testing!
If you are using primitives ,they will be automatically set to their default values. In case of Wrapper calss, if you do not care about actual values, you might leave them to null. You can throw a NullPointerException if they are accessed without initializing them.
For populating it in the list, the simplest way should be create a object of class and adding objects to the list.
class DTO
{
int a;
String b;
float c;
DTO (int a,String b,float c)
{
this.a=a;
this.b=b;
this.c=c;
}
public static void main (String args[])
{
List <DTO> list = new ArrayList<DTO>();
DTO o = new DTO (1,"Test",11.3f);
list.add(o);
}
}
Printing the list and overriding toString() should display the values.
Write a method with Introspector.getBeanInfo(object.getClass()).getPropertyDescriptors() in a small loop to fill fields as needed. You can recursively call this method to fill classes, collections etc.
Other way is a XML deserialization using JAXB, XStream or Abraxas.
Is there any tool that can traversal through all fields and set primitives, 0 for Number (0.0 for Float, Double, 0 for Integer, 0L for Long, but not null as default), something like "test" for String? Also I want that tool to populate Collections (List, Set, Map).
AFAIK, there is nothing that will save you much effort over doing it the simple way. It is a trivial matter to declare the fields with an initializer, or to do some simple default initialization in the constructor(s).
It is probably a good idea to use primitive types rather than wrapper types; e.g. int rather Integer. One advantage is that fields with primitive types are default initialized to 0, 0.0 or false ... saving you the bother.
You can get the type of the field by reflection, and then initialize it to whatever you want, also using reflection.
public static void main(String[] args) {
MyDTO myDTO = new MyDTO();
Field [] fields = myDTO.getClass().getDeclaredFields();
for (Field field: fields){
if (field.getType().equals(Integer.TYPE)){
//Primitives are already initialized to 0, so no need to do anything.
}else if (field.getType().equals(String.class)){
System.out.println("String");
//Invoke setter method with reflection, initialize to ""
}
}
}
I have a basic question about using the "Best Practices" in coding. (I'm using Java, but the question is general to OOP.) When writing method's for a class that are intended to be used in the long run, is it best to leave the return object with or without generics?
To be specific in my case, I'm returning a Map<String, Integer> with the method. Should I specify this in the return statement, or should I simply return a Map?
It is best to use generics whenever possible. It will help avoid runtime exceptions, and it won't force the people using your code to do a bunch of ugly type casting. For example, if you use the following signature:
Map<String, Integer> getMap();
... then the consuming code might look like this:
Map<String, Integer> map = getMap();
Integer val = map.get(key);
... but if you use a signature like this:
Map getMap();
... the consuming code might look like this:
Map<String, Integer> map = (Map<String, Integer)getMap();
Integer val = map.get(key);
By using generics, not only do you save that (Map<String, Integer>) cast, but in the event that you change getMap to actually return a Map<String, Object>, you will get a compile-time error (which is easy to catch and fix), rather than possibly getting an exception when you call map.get(key) and the JRE tries to do an automatic cast of some random Object into an Integer.
You should definitely return a Map<String, Integer> instead of a plain Map if it makes sense in your method, as this will make it easier for others to use said method - after getting the Map<String, Integer> they will be able to retrieve String keys and Integer values without having to cast them from a generic Object every time (this also makes it a little more typesafe as this way they will know what the keys and values are without even reading the javadoc for your method).
So in short, definitely, return generics.
If you are returning a collection, you should include the generic type that is contained by the collection. For example:
public Map<String, Blammo> getBlammoMap(...)
is (IMHO) preferred to
public Map getBlammoMap(...)
Because it
Limits the options of a bad cast (i.e. kapowMap = (Map<String, Kapow> getBlammoMap()).
Tells the consumer what the method is actually returning.
If the method is clearly intended to work with a certain type (i.e. only String), then it's ok to return a List<String>. If the method is generic taking a type parameter T, you can return List<T>.
I would not simply return a Map, because usually it causes confusion and more boiler-plate code to convert to the desired type.
In general, your type parameters, both input and output, should capture the level of specificity of the precise function. In functional programming, they go so far as to say "the types are the documentation." If I were to see Map foo(Arg args) I would think that foo is in no way concerned with the types in the Map it returns, but somehow relies on Args for something." If I were to see Map<T,String> foo(T t, Arg arg) or Map<T, U> foo(T t, U u) I would think "OK, foo produces a Map based on the type of its t and with a String produced by Arg (or by the U from u)."
In terms of preference, clearly you want to be as clear as possible to the future programmer (yourself or others). Just as returning Map without type-params is obscure, so too would returning Map<String, Integer> might be overly restrictive (and thus misleading) if your foo would work equally well with, say, Map<String, Long>
I believe that more specific, the better. If your method is return a map that always has Strings as the key, and Integers as the value, then definitely use the Map has the return type. That way, any calling code knows exactly what they're getting. If the return type was just Map, then the calling code would have no idea what the class the keys and values are (Other than Object).
In general, you should probably always specify paramerize Maps, Lists, etc., so it's known exactly what it contains. This is very helpful when iterating over them and you can use a java foreach.
for (String currKey : myMap.keySet())
{
System.out.println("curr Key: " + currKey + " curr Value: " + myMap.get(currKey));
}
This eliminates any extra iterators or casting.
Ho-ho-ho! A pretty New Year question.
You generally must (MUST) return a proper generic Map<Whatever, YouNeed>. It may sound crazy, but as soon as you use any generic type without type parameters, you're getting into trouble.
The trouble will be as follows: raw types, being used in the code, change the way methods (even seemingly non-related ones) are resolved. Find a presentation by Joshua Bloch and Bill Pugh called "Java Puzzlers: Scraping the Bottom of the Barrel" for details whle I'm preparing an example :) The video with details is at http://www.parleys.com/#id=2168&st=5 (you may want to scroll to slide 44, 5. "Glommer Pile")
So here's an example:
/**
* (c) (as far as I know) Joshua Bloch and Bill Pugh, 2010
*/
public class Glommer<T> {
String glom(Collection<?> objs) {
String result = "";
for (Object o : objs) result += o;
return result;
}
int glom(List<Integer> ints) {
int result = 0;
for (int i : ints) result += i;
return result;
}
public static void main(String args[]) {
List<String> strings = Arrays.asList("1", "2", "3");
System.out.println(new Glommer().glom(strings));
}
}
Question is, whether it
prints 6
prints 123
throws an exception,
or does something else.
Try to guess. Then compile (yes it compiles) and see what happens.
Now that does not apply to your case. But having a habit of always specifying the type, even if it will be just Map<?,?>, is extremely helpful. You won't lose.
The obligatory Java Generics FAQ link
I'm looking at Functional Java and I don't understand what a P1 is. Could anyone explain and/or give an example?
(background: I do know what currying and closures are)
This is taken straight from the Google Code project for Functional Java:
Joint union types (tuples) are products of other types. Products of arities 1-8 are provided (fj.P1 - fj.P8). These are useful for when you want to return more than one value from a function, or when you want to accept several values when implementing an interface method that accepts only one argument. They can also be used to get products over other datatypes, such as lists (zip function).
// Regular Java
public Integer albuquerqueToLA(Map<String, Map<String, Integer>> map) {
Map m = map.get("Albuquerque");
if (m != null)
return m.get("Los Angeles"); // May return null.
}
// Functional Java with product and option types.
public Option<Integer> albuquerqueToLA(TreeMap<P2<String, String>, Integer>() map) {
return m.get(p("Albuquerque", "Los Angeles"));
}
P1 looks like the 1-element, trivial product type. In Haskell it would be written as:
data P1 a = P1 a
(the Identity type in Haskell).
that is, it is a container that holds some other type a.
This type also implements the simplest monad, Identity, which allows for functions to be opaquely applied to the contents of the box.
Computationally, there is no reason to use the Identity monad instead of the much simpler act of simply applying functions to their arguments, however, it can be useful in the design of monad transformer stacks.
The monad implementation of the identity monad is trivial,
return a = P1 a
(P1 m) >>= k = k m
As you can see, this is just function application.
aha, found this post:
>>> Also, P1 is potentially lazy. We use it for the implementation of
>>> Stream, for example.
So instead of returning type T directly, I can have something that returns P1<T>, much like Google Collections Supplier<T>, and have it compute the contained value only when P1._1() is called.
(huh, this blog post Lazy Error Handling in Java was interesting too.....)