通用数据类型转换方法 [英] Generic data type conversion method
问题描述
这个问题是针对 opensas 的另一个问题:在java中建立一个通用的初始化函数
从他的问题变得清楚,他需要从任何数据类型 T1
转换为另一种类型 T2
。当我在这里说数据类型时,我的意思是限于那些通常用于表示原始数据的类型: Integer
, String
, Date
等等。为了这个问题的目的,我们可以考虑将原始元素装箱。
m想知道是否有任何支持在输入和输出都推广到一组支持的数据类型的类型之间进行转换的API。我查看了 Apache Commons' beanutils.converters包,但每个已知输入都有一个单独的转换器类。我正在寻找任何实现如下签名的功能:
static< IN,OUT> OUT转换(IN值,Class< OUT> targetType);
或其他
static< IN,OUT> OUT转换(IN值,OUT默认值);
实现这种映射真的不会太困难,要么使用一堆 else if
指向各种Commons Converters的块,或者 Map< Class<>,Converter>
for相同的目的。但是我想知道这种功能是否支持某个地方。
另外,如果这样做是重复的,我很抱歉。我试图找到类似的问题,当我发现没有匹配这种情况时感到惊讶。
编辑: :
整数i = GenericConverter.convert(123,Integer.class); //返回123
日期d = GenericConverter.convert(1313381772316L,Date.class); //返回今天的日期
Boolean b = GenericConverter.convert(0,Boolean.class); //返回false
Long l = GenericConverter.convert(asdf,Long.class); // RuntimeException
更新:链接的BalusC代码接近mark,Bohemian的答案是一个不错的轻量级解决方案(尽管它不适用于布尔转换)。如果我们想推广这些其他数据类型的转换,那么日期应该单独处理也是正确的。我仍然希望能得到更多的答案 - 尤其是如果有更多的可用的API可用的话。
JDK 8 ,这可以通过新的 java.util.functions.Mapper $ c轻松实现$ c>接口和 lambda表达式。
Mapper< String,Integer> atoi = s - > Integer.valueOf(一个或多个);
Integer r = atoi.map(10);
使用方法引用可以更简单:
Mapper< String,Integer> atoi = Integer :: new;
Integer r = atoi.map(10);
或类似的东西:
列表与LT;长>日期= asList(1344754620310L,1344754854877L);
列表<日期> asDates = dates.map(Date :: new).into(new ArrayList< Date>());
或者酷酷的转换:
列表与LT;整数> myInts =5,4,3,2,1,0,6,7,8,9
.splitAsStream(,)
.map(Integer :: new)
.into(new ArrayList< Integer>());
在JDK8 API的当前实现中,已经定义了一些默认映射器(即 LongMapper
, IntMapper
, DoubleMapper
),还有一个工具类叫做code> Mappers ,它定义了其他一些类似于字符串映射器,身份映射器,常量映射器等的元素。
我不确定如果这是你以后的事情,但它肯定是实现它的一个好方法。
像你所建议的例子:
static< IN,OUT> OUT转换(IN值,Class< OUT> targetType);
可以使用 Mappers
实用程序类实现:
Mapper< String,Integer> atoi = Mappers.instantiate(String.class,Integer.class);
Integer r = atoi.map(10);
您的签名:
static< IN,OUT> OUT转换(IN值,OUT默认);
可以用类似的方式实现:
Mapper< String,Integer> atoi = chain(substitute(null,0),Integer :: new);
Integer r = atoi.map(null); //产生0
同样,这样的代码...
列表< String> data = asList(0,null,2,null,4,null,6);
列表<整数> (new ArrayList< Integer>()); myInts = data.map(chain(substitute(null,0),Integer :: new)
System.out.println(myInts);
会产生: [0,0,2,0,4,0 ,6]
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.
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]
这篇关于通用数据类型转换方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!