2

commons-collections 3.2.1以下单行代码中,可以很好地检索myProperty内部对象的值myCollection

Collection<MyType> myTypes = (Collection<MyType>) CollectionUtils.collect(myCollection, new BeanToPropertyValueTransformer("myProperty"))

唯一的缺点是不支持泛型,所以需要进行类型转换。

什么是可以commons-collection4利用泛型的解决方案?

4

2 回答 2

1

显然他们BeanToPropertyValueTransformerapache-commons-collection4.

我设法通过定义自定义来实现相同的行为Transformer。泛型的引入消除了强制转换输出集合的必要性:

Collection<MyInputType> myCollection = ...
Collection<MyType> myTypes = CollectionUtils.collect(myCollection, new Transformer<MyInputType, MyType>() {
    @Override
    public MyType transform(MyInputType input) {
        return input.getMyProperty();
    }
}

您也可以编写自己的Transformer使用反射的

class ReflectionTransformer<O>
        implements
        Transformer<Object, O> {

    private String  reflectionString;

    public ReflectionTransformer(String reflectionString) {
        this.reflectionString = reflectionString;
    }

    @SuppressWarnings("unchecked")
    @Override
    public O transform(
            Object input) {
        try {
            return (O) BeanUtils.getProperty(input, reflectionString);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}

并像以前一样使用它BeanToPropertyValueTransformer

Collection<MyType> myTypes = CollectionUtils.collect(myCollection, new ReflectionTransformer<MyType>("myProperty"));
于 2016-04-04T12:29:38.807 回答
0

尝试使用下面的类(使用 commons-collection4) -

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.InvocationTargetException;

public class BeanToPropertyValueTransformer implements Transformer {

    private final Log log = LogFactory.getLog(this.getClass());

    private String propertyName;
    private boolean ignoreNull;
    
    public BeanToPropertyValueTransformer(final String propertyName) {
        this(propertyName, false);
    }

    public BeanToPropertyValueTransformer(final String propertyName, final boolean ignoreNull) {
        super();

        if ((propertyName != null) && (propertyName.length() > 0)) {
            this.propertyName = propertyName;
            this.ignoreNull = ignoreNull;
        } else {
            throw new IllegalArgumentException(
                "propertyName cannot be null or empty");
        }
    }
    
    public Object transform(final Object object) {

        Object propertyValue = null;

        try {
            propertyValue = PropertyUtils.getProperty(object, propertyName);
        } catch (final IllegalArgumentException e) {
            final String errorMsg = "Problem during transformation. Null value encountered in property path...";

            if (ignoreNull) {
                log.warn("WARNING: " + errorMsg + e);
            } else {
                final IllegalArgumentException iae = new IllegalArgumentException(errorMsg);
                if (!BeanUtils.initCause(iae, e)) {
                    log.error(errorMsg, e);
                }
                throw iae;
            }
        } catch (final IllegalAccessException e) {
            final String errorMsg = "Unable to access the property provided.";
            final IllegalArgumentException iae = new IllegalArgumentException(errorMsg);
            if (!BeanUtils.initCause(iae, e)) {
                log.error(errorMsg, e);
            }
            throw iae;
        } catch (final InvocationTargetException e) {
            final String errorMsg = "Exception occurred in property's getter";
            final IllegalArgumentException iae = new IllegalArgumentException(errorMsg);
            if (!BeanUtils.initCause(iae, e)) {
                log.error(errorMsg, e);
            }
            throw iae;
        } catch (final NoSuchMethodException e) {
            final String errorMsg = "No property found for name [" +
                propertyName + "]";
            final IllegalArgumentException iae = new IllegalArgumentException(errorMsg);
            if (!BeanUtils.initCause(iae, e)) {
                log.error(errorMsg, e);
            }
            throw iae;
        }

        return propertyValue;
    }

    public String getPropertyName() {
        return propertyName;
    }

    public boolean isIgnoreNull() {
        return ignoreNull;
    }
}
于 2021-06-28T18:20:06.233 回答