如何将功能添加到优先级队列? (甚至可能)

时间:2014-11-04 17:40:15

标签: java priority-queue

我知道什么是优先级队列,我知道如何添加字符串/整数。但现在我想为它添加功能。 (如果这有道理??)。我还没准备好改变任何函数的返回类型。

我想知道我该怎么做呢?我创建了一个原始类型优先级队列

PriorityQueue  prq = new PriorityQueue ();
prg.offer(login());

现在,我不是编码天才,我也在学习。所以我想看看它是否可行。如果不可能有替代解决方案吗?

我的pop()函数将运行弹出的函数。我的大部分功能都无效。

我得到的一个想法:我是否应该插入字符串并根据我弹出的字符串执行switch语句()???

3 个答案:

答案 0 :(得分:0)

您不能将该函数用作优先级队列的参数(在java中),但只要该函数的返回类型与所需参数匹配,您就可以使用该函数的返回值。

offer()中的参数类型由泛型指定。这是代码示例。

public static int login(){

    return 0;
}

public static void main (String[] args){


    PriorityQueue<Integer>  prq = new PriorityQueue<Integer>();
    prg.offer(login());
}

然后,您可以将整数更改为函数login()的返回类型。

答案 1 :(得分:0)

一般来说,可以做这样的事情,但我建议你考虑一下。实施有点笨拙。

首先,您正在使用优先级队列。这意味着您希望按优先级顺序接收添加到其中的内容。优先级队列是有序集合。为此,您放入其中的项目必须为Comparable。这就是String或Integer的优先级队列工作的原因。它们都是Comparable - 如果你在队列中有两个字符串,那么很容易分辨出哪个是第一个,因为字符串有一个自然顺序。尽管如此,必须说在现实生活中,你通常不会分配字符串优先级。优先级队列应该表示哪些事情更迫切需要处理,哪些事情更少。所以通常优先级更有可能被实现为某种数字或枚举。

因此,除了将一个函数放入队列之外,还需要在将其放入队列时为其分配优先级,这将告诉谁从队列中读取哪个函数更难以执行。他只是按优先顺序得到它们。

因此我们需要定义某种对象,它将封装函数和优先级:

public final class PrioritizedPerformer implements Comparable<PrioritizedPerformer> {

    /**
     * Actor interface. Represents a way to run a function.
     */
    public interface Actor {
        void perform();
    }

    /**
     * Available priorities
     */
    public enum Priority { URGENT, HIGH, MEDIUM, LOW };

    private Priority priority;
    private Actor actor;

    /**
     * Constructor that allows creating PrioritizedPerformer objects with a given priority and actor.
     * 
     * @param priority  Priority of this object when placed in a priority queue.
     * @param actor     Actor representing a function to be performed.
     */
    public PrioritizedPerformer(Priority priority, Actor actor) {

        // Don't allow null priorities, this will cause problems in priority queues.
        if ( priority == null ) {
            throw new IllegalArgumentException("Must provide valid priority");
        }
        this.priority = priority;

        // Don't allow null actors. The action has to be available.
        if ( actor == null ) {
            throw new IllegalArgumentException("Must provide valid actor");
        }
        this.actor = actor;
    }

    /* Allows prioritizing one PrioritizedPerformer over another.
     * 
     * @see java.lang.Comparable#compareTo(java.lang.Object)
     */
    @Override
    public int compareTo(PrioritizedPerformer o) {
        return priority.compareTo(o.priority);
    }

    /**
     * Perform whatever action the actor represents.
     */
    public void perform() {
        actor.perform();
    }
}

现在我们有了这个,我们可以将这种类型的对象放入优先级队列:

    PriorityQueue<PrioritizedPerformer> queue = new PriorityQueue<PrioritizedPerformer>();

    queue.offer(new PrioritizedPerformer(
            PrioritizedPerformer.Priority.HIGH,
            new PrioritizedPerformer.Actor() {
                public void perform() {
                    login();
                }
            }));
    queue.offer(new PrioritizedPerformer(
            PrioritizedPerformer.Priority.LOW,
            new PrioritizedPerformer.Actor() {
                public void perform() {
                    quit();
                }
            }));
    queue.offer(new PrioritizedPerformer(
            PrioritizedPerformer.Priority.URGENT,
            new PrioritizedPerformer.Actor() {
                public void perform() {
                    returnThree();
                }
            }));

我们在这里做的是使用给定的PrioritizedPerformer构建每个Priority对象和执行我们希望它执行的函数的匿名Actor

现在我们可以运行:

    queue.remove().perform();

这将从队列中删除最高优先级的对象,并运行其perform()方法,该方法调用其内部Actor的{​​{1}}方法。在这种情况下,它将采用优先级为perform()的那个,恰好运行函数URGENT

所以这会做你要求的。然而我建议反对它。它只能执行没有参数的函数(或者只调用具有预定参数的特定函数)。你无法传递类似returnThree()的内容,因为当你需要执行它时,你无法将数字传递给该函数。

这导致使用全局范围字段将数据传递给各种函数而不是参数。这反过来会导致可读性问题,缺少封装,这意味着您的参数可能会被您不打算更改它们的方法所改变。这是各种各样的坏事。此外,在此特定设置中,如果您不知道接下来要运行哪个功能,您将如何知道在全局范围内设置哪些参数?

答案 2 :(得分:-1)

您目前正在做的是将该函数的返回值放入队列中。因此,函数执行,然后将它生成的值放入队列。相反,您可以拥有Runnable的队列,然后在其上调用run()方法:

PriorityQueue<Runnable> queue = new PriorityQueue<Runnable>();
queue.offer( new Runnable() { public void run() { login(); } );

queue.remove().run();

或者,如果使用Java 8:

PriorityQueue<Runnable> queue = new PriorityQueue<>();
queue.offer(() -> login(););