按对象属性值查找 [英] Find by object property value

查看:154
本文介绍了按对象属性值查找的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我有以下情况。我有一些类A,它有类型B的对象列表。
类型B有两个属性X,Y类型字符串和两个getters getX()getY()。
我想在A类中有一个方法,从一个给定的string值选择的B对象的集合返回一个对象。例如:


I have the following situation. I have some class A, which has list of objects of type B. Type B has two properties X, Y of type string and two getters getX() getY(). I would like to have a method in class A such that returns an object from collection of B objects selected by given value of string. For example:

B findElementByX(String x) {
    for (B i : list) {
         if (i.getX().equals(x)
             return i;
    }
    return null;
}

对于其他属性,我将有几乎相同的代码,btu而不是getX(),将有getY()。对我来说,它不必要的冗余代码。我的问题是:如何写这个方法为了有一个方法通过X或Y属性值找到?这是一个通用的方法来解决这个在Java?

For the other property Y i would have almost the same code, btu instead of getX(), there will be getY(). For me its unnecessary redundance of code. My question is: how to write this method in order to have one method to find by either X or Y property value? Is this a generic way to solve this in Java?

推荐答案

您可以通过使用 Guava ,它提供类似于函数式语言样式列表解析的东西。

You can reduce code size for things like this by using something like Guava, which supplies something resembling functional language style list comprehension.

你也可以通过定义一个接口

You can also roll some of this yourself, by defining an interface

public interface Predicate<T> {
    boolean apply(T obj);
}

,然后使用它创建finder方法:

and then creating a finder method using it:

B findElementByPredicate(Predicate<B> predicate) {
    for (B b : list) {
        if (predicate.apply(b))
            return b;
    }
    return null;
}

您也可以使用反射的字段。实现arne.b的答案中定义的接口,你可以定义

You can also (as noted in a comment) use reflection to get the value of a field. Implementing the interface defined in arne.b's answer, you can define

public class ReflectivePropertyExtractor<T, P> implements PropertyExtractor<T, P> {

    String fieldName;

    public ReflectivePropertyExtractor(String fieldName) {
        this.fieldName = fieldName;
    }

    @Override
    public P getProperty(T obj) {
        try {
            Method m = B.class.getMethod(makeAccessorName());
            return (P) m.invoke(obj);
        } catch (InvocationTargetException e) {
            return null;
        } catch (NoSuchMethodException e) {
            return null;
        } catch (IllegalAccessException e) {
            return null;
        }
    }

    private String makeAccessorName() {
        return "get" + capitalize(fieldName);
    }

    private String capitalize(String s) {
        if ((s == null) || (s.length() == 0))
            return s;
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }

}

对于指定的字段名,并使用他在他的回答中描述的或基于它做一个谓词:

to make a property extractor that works for a specified field name, and either use that as he described in his answer or make a predicate based on it:

public class PropertyMatchPredicate<T, P> implements Predicate<T> {
    private final P matchValue;
    private final PropertyExtractor<T, P> extractor;

    public PropertyMatchPredicate(P matchValue, PropertyExtractor<T, P> extractor) {
        this.matchValue = matchValue;
        this.extractor = extractor;
    }

    @Override
    public boolean apply(T obj) {
        return matchValue.equals(extractor.getProperty(obj));
    }
}

然后在 findByPredicate 上面:

B findElementByProperty(String matchField, final String matchValue) {
    final ReflectivePropertyExtractor<B, String> extractor = new ReflectivePropertyExtractor<B, String>(matchField);
    return findElementByPredicate(new PropertyMatchPredicate<B, String>(matchValue, extractor));
}

如果你只处理两个属性,所有这些战术都可能会增加代码大小而不是减少它。优点只会发生在更大的规模,你可能付出代价,使你的代码对于不熟悉功能风格和/或反射的人更不容易阅读。

If you are only dealing with two properties, all of these tactics will likely increase code size rather than decreasing it. The advantages only happen at greater scale, and you may pay a price in making your code less readable to people unfamiliar with functional style and/or reflection.

这篇关于按对象属性值查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆