该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-12-22
看大牛们吹的漫天都是牛!
|
|
返回顶楼 | |
发表时间:2010-12-22
最后修改:2010-12-22
序列化和反序列化接口初步定义如下:
各部分的结构初步设计完毕,已经考虑了目前已知的各种扩展,大致如下: public abstract class JSON { public static Object parse(String text); public static JSONObject parseObject(String text); public static JSONArray parseArray(String text); public static <T> List<T> parseArray(Class<T> clazz, String text); public static <T> T parseObject(Class<T> clazz, String text); public static String toJSONString(Object object); // 输出JSON String public static String toJSONString(Object object, boolean prettyFormat); // 可选格式化输出JSON String public static String toJSONString(Object object, JavaBeanHandler javaBeanHandler); // 使得可以对JavaBean做特别处理 public static String toJSONStringEx(Object object) { // 使用CGLib实现JavaBean的序列化 return toJSONString(object, false, CGLibJavaBeanHandler.getInstance()); } } public interface JSONAware { String toJSONString(); } public interface JSONStreamAware { void writeJSONString(Appendable out); } public class JSONArray extends JSON implements List<Object>, JSONAware { // ... } public class JSONObject extends JSON implements Map<String, Object>, JSONAware { // ... } public interface JSONParser { Object parse(); void parseArray(Collection array); void parseObject(Map object); } // 使用可以扩展JSONParser,使得能够JSONString -> JavaBean,不需要额外的步骤 public interface ExtJSONParser extends JSONParser { void parseObject(Object object); <T> T parseObject(Class<T> clazz); void parseArray(Class<?> clazz, Collection array); } public class DefaultJSONParser implements JSONParser { // ... } public class CGLibExtJSONParser extends DefaultJSONParser implements ExtJSONParser { // ... } public interface JSONVisitor { JavaBeanHandler getJavaBeanHandler(); void setJavaBeanHandler(JavaBeanHandler javaBeanHandler); void accept(Object object); void acceptBean(JSONAware javaBean); void acceptBean(JSONStreamAware javaBean); void acceptBean(Object javaBean); void acceptNull(); void acceptValue(Date value); void acceptValue(Number value); void acceptValue(String value); void acceptValue(Boolean value); void acceptKey(String key); void acceptArray(Collection<?> array); void acceptObject(Map<?, ?> object); void acceptEntry(Map.Entry<?, ?> entry); void visitBean(JSONStreamAware object); void endVisitBean(JSONStreamAware object); void visitBean(JSONAware object); void endVisitBean(JSONAware object); void visitBean(Object object); void endVisitBean(Object object); boolean visitObject(Map<?, ?> map); void endVisitObject(Map<?, ?> map); boolean visitEntry(Map.Entry<?, ?> entry); void endVisitEntry(Map.Entry<?, ?> entry); boolean visitArray(Collection<?> array); void endVisitArray(Collection<?> array); void visitValue(Number value); void endVisitValue(Number value); void visitValue(Date value); void endVisitValue(Date value); void visitValue(boolean value); void endVisitValue(boolean value); void visitValue(String value); void endVisitValue(String value); void visitNull(); void endVisitNull(); boolean visitKey(String key); void endVisitKey(String key); void preVisit(Object value); void postVisit(Object value); } public interface JSONOutputVisitor extends JSONVisitor { Appendable getOut(); void print(char ch); void print(String text); } public class JSONVisitorAdapter implements JSONVisitor { // ... } public class DefaultJSONOutputVisitor extends JSONVisitorAdapter implements JSONOutputVisitor { } public class JSONPrettyFormatOutputVisitor extends DefaultJSONOutputVisitor { } public interface JavaBeanHandler { void handle(Object javaBean, JSONVisitor visitor); } public class CGLibJavaBeanHandler implements JavaBeanHandler { } |
|
返回顶楼 | |
发表时间:2010-12-22
最后修改:2010-12-22
JSON类是主要入口,包括了toJSONString和parse系列方法。
JSON、JSONArray、JSONObject,这样的结构和其他的JSON库是类似的(如SimpleJSON、JSON-lib)。 其余就是Parser和Visitor的结构了。Visitor负责序列化,Parser负责反序列化。 注明一下,这里的Visitor是Visitor模式的变种,缺省Visitor模式的accept方法是在被访问对象中实现的,我这里的情况比较特殊,accept系列方法在Visitor中实现乐。 |
|
返回顶楼 | |
发表时间:2010-12-22
最后修改:2010-12-22
举例:
User user = new User(); List<User> userList = new ArrayList<User>(); String jsonString1 = JSON.toJSONStringEx(user); String jsonString2 = JSON.toJSONStringEx(userList); User user1 = JSON.parseObject(User.class, jsonString1 ); List<User> userList1 = JSON.parseArray(User.class, jsonString2 ); |
|
返回顶楼 | |
发表时间:2010-12-22
wenshao 写道 谢谢校长进行codereview,指出了其中isDigit函数的问题,尝试多种办法测试之后,发现综合最快的是范围判断。linux kernel的isDigit算法,在Java中性能不稳定,只是在Windows XP 32bit JVM中-client参数时最快,其他测试环境都慢。
最终采用的实现如下,很简单的: public final boolean isDigit(char ch) { return ch >= '0' && ch <= '9'; } linux kernel的isDigit算法如下: private static final boolean[] digitBits = new boolean[256]; static { for (char ch = '0'; ch <= '9'; ++ch) { digitBits[ch] = true; } } public final boolean isDigit(char ch) { return digitBits[ch]; } 这是典型的空间换时间的思路,但在java中,这是性能不稳定的算法,估计是hotspot搞鬼了。 这次调整之后,性能又提升了几个百分点。 温少,身为阿里的大P,说话可要严谨奥,有些事情可以拍脑袋想,但是要讲出来,还是要思量,经过验证,总说“性能提高几个百分点”,什么情况,到底几个?测试的场景是啥子?牛可以吹,但是骨子里还是要严谨的啊 |
|
返回顶楼 | |
发表时间:2010-12-22
最后修改:2010-12-23
举例说明API:
public static class User { private String name; private int age; private BigDecimal salary; private Date birthdate; // 支持日期 public Date getBirthdate() { return birthdate; } public void setBirthdate(Date birthdate) { this.birthdate = birthdate; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public BigDecimal getSalary() { return salary; } public void setSalary(BigDecimal salary) { this.salary = salary; } } public static class Group { private List<User> users = new ArrayList<User>(); private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public List<User> getUsers() { return users; } // 支持泛性 // 还支持另外一种写法 public void setUsers(List<? extends User> users) public void setUsers(List<User> users) { this.users = users; } } public void testComposite() throws Exception { Group group = new Group(); group.setName("神棍"); User user = new User(); user.setName("校长"); user.setAge(3); user.setSalary(new BigDecimal("123456789.0123")); user.setSalary(new BigDecimal("123456789.0123")); group.getUsers().add(user); String jsonString = JSON.toJSONStringEx(group); System.out.println(jsonString); JSON.parseObject(jsonString); Group group1 = JSON.parseObject(Group.class, jsonString); Assert.assertEquals(group.getName(), group1.getName()); User user1 = group1.getUsers().get(0); Assert.assertEquals(user.getAge(), user1.getAge()); Assert.assertEquals(user.getName(), user1.getName()); Assert.assertEquals(user.getSalary(), user1.getSalary()); } |
|
返回顶楼 | |
发表时间:2010-12-22
基本可以收工了吧
性能已经解决了,扩展性已经解决了,功能还算完整的,日期、组合对象、泛型都支持了。。。 为了一个吹牛,连续两天加班到晚上11点多,没有加班工资的加班,可怜啊。。。 |
|
返回顶楼 | |
发表时间:2010-12-22
superwwt 写道
sky3380 写道
wenshao 写道
谢谢校长进行codereview,指出了其中isDigit函数的问题,尝试多种办法测试之后,发现综合最快的是范围判断。linux kernel的isDigit算法,在Java中性能不稳定,只是在Windows XP 32bit JVM中-client参数时最快,其他测试环境都慢。
最终采用的实现如下,很简单的: public final boolean isDigit(char ch) { return ch >= '0' && ch <= '9'; } linux kernel的isDigit算法如下: private static final boolean[] digitBits = new boolean[256]; static { for (char ch = '0'; ch <= '9'; ++ch) { digitBits[ch] = true; } } public final boolean isDigit(char ch) { return digitBits[ch]; } 这是典型的空间换时间的思路,但在java中,这是性能不稳定的算法,估计是hotspot搞鬼了。 这次调整之后,性能又提升了几个百分点。 请教一下,为什么不能用Character.isDigit(c),也是因为性能吗? 为啥是256个呢?不就只要判断0-9就行了么? 会越界的,不过Java里的char值可不止256个 |
|
返回顶楼 | |
发表时间:2010-12-23
我想, 各位, 开源是需要经过各种手续的。 我也很期待温少的小东东能拿出来给大家看看, 或者能用上。 我们会给大家更大一些的惊喜。
|
|
返回顶楼 | |
发表时间:2010-12-23
最后修改:2010-12-23
fengjia10 写道 wenshao 写道 谢谢校长进行codereview,指出了其中isDigit函数的问题,尝试多种办法测试之后,发现综合最快的是范围判断。linux kernel的isDigit算法,在Java中性能不稳定,只是在Windows XP 32bit JVM中-client参数时最快,其他测试环境都慢。
最终采用的实现如下,很简单的: public final boolean isDigit(char ch) { return ch >= '0' && ch <= '9'; } linux kernel的isDigit算法如下: private static final boolean[] digitBits = new boolean[256]; static { for (char ch = '0'; ch <= '9'; ++ch) { digitBits[ch] = true; } } public final boolean isDigit(char ch) { return digitBits[ch]; } 这是典型的空间换时间的思路,但在java中,这是性能不稳定的算法,估计是hotspot搞鬼了。 这次调整之后,性能又提升了几个百分点。 温少,身为阿里的大P,说话可要严谨奥,有些事情可以拍脑袋想,但是要讲出来,还是要思量,经过验证,总说“性能提高几个百分点”,什么情况,到底几个?测试的场景是啥子?牛可以吹,但是骨子里还是要严谨的啊 一个8K的文本,来自真是业务场景的数据,里面有很多数字,这个场景恰好是被Jackson针对性优化过的那种,isDigit函数性能的提升,使得比Jackson在这个场景下的差距又拉大的一点,大约3%的性能提升。 尻,明明标题说了是吹牛,你那么认真干嘛,吓唬我么!!! |
|
返回顶楼 | |