首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过java中的一组参数找到最合适的对象

通过java中的一组参数找到最合适的对象
EN

Stack Overflow用户
提问于 2014-01-22 08:34:59
回答 4查看 146关注 0票数 3

我有一套东西。该对象根据请求参数计算某些数字。我们叫他们计算器吧。每个计算器都有此计算器最适合的特定类型请求的说明。例如,

代码语言:javascript
复制
Calculator1 : with this parameters : price > 10, gender = male, geo_id = 1, 2 or 3.
Calculator2 : with this parameters : price < 5, gender = male,  geo_id = 1, 2. 

对于请求:price = 11, gender = male, geo_id = 2,我应该得到最合适的calculator1,然后是calculator2。

对于请求:price = 4, gender = male, geo_id = 2,我应该得到calculator2,然后是calculator1。

对于请求:price = 3, gender = female, geo_id = 5,我应该只得到第二个。

现在我和Lucene一起做了,但是它并不适合这个任务。你能给我推荐一些图书馆或方法吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-01-22 12:08:44

我的建议是使用比较器。请看下面课程的草图。

代码语言:javascript
复制
import java.util.HashMap;
import java.util.Map;

public abstract class Calculator {
    public static Map<String, Integer> weights;
    static {
        weights = new HashMap<String, Integer>();
        weights.put("price", 10);
        weights.put("gender", 2);
        weights.put("geo", 5);
    }

    public abstract int calculate(Map<String, Integer> request);
    public abstract int fitnessFor(Map<String, Integer> request);
}

您可以使用权重来调整单个请求参数的相对重要性。

代码语言:javascript
复制
import java.util.Map;

public class Calculator1 extends Calculator {

    public int calculate(Map<String, Integer> request) {
        return -1;
    }

    @Override
    public int fitnessFor(Map<String, Integer> request) {
        int fitness = -1;
        Integer price = request.get("price");
        if (price == null)
            return fitness;

        if (price > 10)
            fitness += weights.get("price");

        return fitness;
    }

    public String toString() { return "Calculator1"; }
}

Calculator1只关心昂贵的物品。

代码语言:javascript
复制
import java.util.Map;

public class Calculator2 extends Calculator {

    public int calculate(Map<String, Integer> request) {
        return -1;
    }

    @Override
    public int fitnessFor(Map<String, Integer> request) {
        int fitness = -1;
        Integer price = request.get("price");
        if (price == null)
            return fitness;

        if (price < 5)
            fitness += weights.get("price");

        Integer gender = request.get("gender");
        if (gender == null)
            return fitness;

        if (gender == 1)
            fitness += weights.get("gender");

        return fitness;
    }

    public String toString() { return "Calculator2"; }  
}

Calculator2关心的是价格较低的商品(尤指价格较低的商品)。如果是性别1。

比较器只是比较计算器相对于请求的适配性:

代码语言:javascript
复制
import java.util.Comparator;
import java.util.Map;

public class CalcComparator implements Comparator<Calculator> {
    private Map<String, Integer> request;

    public CalcComparator(Map<String, Integer> request) {
        this.request = request;
    }

    @Override
    public int compare(Calculator c1, Calculator c2) {
        int c1Fitness = c1.fitnessFor(request);
        int c2Fitness = c2.fitnessFor(request);

        if (c1Fitness == c2Fitness)
            return 0;

        if (c1Fitness < c2Fitness)
            return 1;

        return -1;
    }
}

试一试:

代码语言:javascript
复制
public class Main {

    public static void main(String[] args) {
        Map<String, Integer> request = new HashMap<String, Integer>();
        request.put("price", 5);
        request.put("gender", 1);

        List<Calculator> calculators = new ArrayList<Calculator>();
        calculators.add(new Calculator1());
        calculators.add(new Calculator2());

        Collections.sort(calculators, new CalcComparator(request));

        System.out.println("For request: "+request);
        for (Calculator c : calculators) {
            System.out.println("\t"+c.toString() + "( fitness " + c.fitnessFor(request) + ")");
        }
    }
}

这只是一个说明这个想法的草图。您可能希望为请求参数引入一个枚举,可能会引入一个请求类,很可能完全改变适应度的计算方式,使某些字段成为私有字段并封装它们,等等。

其优点是,您可以根据所有计算器的适合性,轻松地获得它们的排序。

票数 2
EN

Stack Overflow用户

发布于 2014-01-22 11:07:45

你也许可以试试这样的方法:

代码语言:javascript
复制
public enum Calculator
{
    CALC1
    {
        @Override
        protected int matchCount( Map parameters )
        {
            // TODO count how many conditions match
            return 0;
        }

        @Override
        protected int calc( Map parameters )
        {
            // TODO
            return 0;
        }
    },

    CALC2
    {
        @Override
        protected int matchCount( Map parameters )
        {
            // TODO count how many conditions match
            return 0;
        }

        @Override
        protected int calc( Map parameters )
        {
            // TODO
            return 0;
        }
    };

    protected abstract int matchCount( Map parameters );
    protected abstract int calc( Map parameters );

    public int doCalc( Map parameters )
    {
        Calculator  mostSuited = null;
        int  maxCount = 0;

        for ( Calculator  calc : values() )
        {
            int  matchCount = calc.matchCount( parameters );

            if ( matchCount > maxCount )
            {
                mostSuited = calc;
            }
        }

        return mostSuited.calc( parameters );
    }
}

使用上面的方法是通过调用:int result = Calculator.doCalc( parameters )

票数 1
EN

Stack Overflow用户

发布于 2014-01-22 11:19:58

如果我正确地理解了您,我建议您使用规格说明设计模式,这种模式在这种情况下是使用的。像Lucene这样的高级图书馆不需要这样简单的任务。规范模式的优点是它将所有过滤逻辑分组和封装。您的实现可能会有所不同,但下面是一个简单的示例,说明了它的样子。

代码语言:javascript
复制
public interface Specification<T> {
    boolean isSatisfiedBy(T candidate);
    Specification<T> and(Specification<T> specification);
    Specification<T> or(Specification<T> specification);
    Specification<T> not(Specification<T> specification);
}

public abstract class Calculator {
    // ...
}

public class Calculator1 extends Calculator implements Specification<Request> {
    public boolean isSatisfiedBy(Request request) {
        // check if the request fits this calculator
    }
}

public class Calculator2 extends Calculator implements Specification<Request> {
    public boolean isSatisfiedBy(Request request) {
        // check if the request fits this calculator
    }
}

然后,您可以拥有一个集合或一个计算器池,以便

代码语言:javascript
复制
public class Calculators {
    private final List<RequestSpecification> calculators;
    public Calculator getOneSuitedFor(Request request) {
        for (Calculator calculator : calculators) {
            if (calculator.isSatisfiedBy(request)) {
                return calculator;
            }
        }
        return null;
    }
}

在这里,你将如何使用它

代码语言:javascript
复制
Calculator calculator = Calculators.getOneSuitedFor(request);

或者,如果需要,您可以通过使用组合(参见上面的参考链接)来继续并扩展它,这允许根据上下文的不同规范进行逻辑链接和组合。然而,这将需要与上面的类设计略有不同,但更灵活。

代码语言:javascript
复制
final Request request;

Specification<Calculator> price = new Specification<>() {
     public boolean isSatisfiedBy(Calculator calculator) {
         return calculator.supportsPrice(request.getPrice());
     }
};

Specification<Calculator> gender = new Specification<>() {
     public boolean isSatisfiedBy(Calculator calculator) {
         return calculator.supportsGender(request.getGender());
     }
};

Specification<Calculator> region = new Specification<>() {
     public boolean isSatisfiedBy(Calculator calculator) {
         return calculator.supportsRegion(request.getRegion());
     }
};

Specification calcSpec = price.and(gender).and(region);
boolean isSatisfied = calcSpec.isSatisfiedBy(calculator);

另一个有趣的例子是使用命名规范。

代码语言:javascript
复制
Specification<Calculator> teenager = new Specification<>() {
     public boolean isSatisfiedBy(Calculator calculator) {
         return calculator.getAge() >= 13 && calculator.getAge() <= 19;
     }
};

Specification<Calculator> male = new Specification<>() {
     public boolean isSatisfiedBy(Calculator calculator) {
         return calculator.getGender().equals("male");
     }
};

Specification<Calculator> fromEurope = new Specification<>() {
     public boolean isSatisfiedBy(Calculator calculator) {
         return calculator.getRegion().equals("Europe");
     }
};

Specification<Calculator> calcSpec = teenager.and(male).and(fromEurope);
boolean isSatisfied = calcSpec.isSatisfiedBy(calculator);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21277865

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档