【问题标题】:Generate Map<String,String> from POJO从 POJO 生成 Map<String,String>
【发布时间】:2010-07-09 18:35:32
【问题描述】:

我有一个 POJO,和一个(目前尚未构建的)类,它将返回它的列表。我想自动生成 POJO 作为 Map 访问所需的代码。这是一个好主意吗,是否可以自动执行,我是否需要为我想以这种方式处理的每个 POJO 手动执行此操作?

谢谢, 安迪

【问题讨论】:

    标签: java android pojo listactivity


    【解决方案1】:

    您可以为此使用Commons BeanUtils BeanMap

    Map map = new BeanMap(someBean);
    

    更新:由于 Android 中存在一些明显的库依赖问题,这不是一个选项,这里有一个基本的启动示例,您可以如何在 Reflection API 的帮助下做到这一点:

    public static Map<String, Object> mapProperties(Object bean) throws Exception {
        Map<String, Object> properties = new HashMap<>();
        for (Method method : bean.getClass().getDeclaredMethods()) {
            if (Modifier.isPublic(method.getModifiers())
                && method.getParameterTypes().length == 0
                && method.getReturnType() != void.class
                && method.getName().matches("^(get|is).+")
            ) {
                String name = method.getName().replaceAll("^(get|is)", "");
                name = Character.toLowerCase(name.charAt(0)) + (name.length() > 1 ? name.substring(1) : "");
                Object value = method.invoke(bean);
                properties.put(name, value);
            }
        }
        return properties;
    }
    

    如果java.beans API 可用,那么您可以这样做:

    public static Map<String, Object> mapProperties(Object bean) throws Exception {
        Map<String, Object> properties = new HashMap<>();
        for (PropertyDescriptor property : Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors()) {
            String name = property.getName();
            Object value = property.getReadMethod().invoke(bean);
            properties.put(name, value);
        }
        return properties;
    }
    

    【讨论】:

    • 天哪!这看起来超级有用!你知道它对性能的影响吗?
    • 反射总是有性能成本的。没有什么可反对的。但是你可以相信 BeanUtils 的人已经尽可能地优化了它。这是一个非常受欢迎的图书馆。
    • 酷。我是否必须在我的 POJO 上实现任何类型的接口,或者使用 get* 命名就足够了(我正在使用不可变 POJO 和通过使用 Builder 实例化的私有构造函数)?
    • 它只是在JavaBean™ specification 之后,是的。虽然不确定私有 c'tors,但在逻辑上似乎不需要公共无参数构造函数来基于现有实例生成地图。
    • 我同意。 *交叉手指*。感谢您的帮助!
    【解决方案2】:

    这是我自己的实现,没有任何依赖关系。它不是复制对象的状态,而是在 pojo 上实现一个实时 Map。 Android doesn't support java.beans,但你可以改用openbeans

    import java.beans.*;  // Or, import com.googlecode.openbeans.*
    import java.util.*;
    
    public class BeanMap extends AbstractMap<String, Object> {
        private static final Object[] NO_ARGS = new Object[] {};
        private HashMap<String, PropertyDescriptor> properties;
        private Object bean;
    
        public BeanMap(Object bean) throws IntrospectionException {
            this.bean = bean;
            properties = new HashMap<String, PropertyDescriptor>();
            BeanInfo info = Introspector.getBeanInfo(bean.getClass());
            for(PropertyDescriptor property : info.getPropertyDescriptors()) {
                properties.put(property.getName(), property);
            }
        }
    
        @Override public Object get(Object key) {
            PropertyDescriptor property = properties.get(key);
            if(property == null)
                return null;
            try {
                return property.getReadMethod().invoke(bean, NO_ARGS);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override public Object put(String key, Object value) {
            PropertyDescriptor property = properties.get(key);
            try {
                return property.getWriteMethod().invoke(bean, new Object[] {value});
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        @Override public Set<Map.Entry<String, Object>> entrySet() {
            HashSet<Map.Entry<String, Object>> result = new HashSet<Map.Entry<String, Object>>(properties.size() * 2);
            for(PropertyDescriptor property : properties.values()) {
                String key = property.getName();
                Object value;
                try {
                    value = property.getReadMethod().invoke(bean, NO_ARGS);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
                result.add(new PropertyEntry(key, value));
            }
            return Collections.unmodifiableSet(result);
        }
    
        @Override public int size() { return properties.size(); }
    
        @Override public boolean containsKey(Object key) { 
            return properties.containsKey(key);
        }
    
        class PropertyEntry extends AbstractMap.SimpleEntry<String, Object> {
            PropertyEntry(String key, Object value) {
                super(key, value);
            }
    
            @Override public Object setValue(Object value) {
                super.setValue(value);
                return BeanMap.this.put(getKey(), value);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-02
      • 1970-01-01
      相关资源
      最近更新 更多