2014-11-04 73 views
0

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

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

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

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

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

我有一个想法:我应该只是插入字符串,并根据哪个字符串做一个switch语句我弹出()?

+1

Java不是JavaScript,函数(Java中的“方法”)不是可以分配给变量(甚至是匿名变量)的东西,然后传递。编程模型相当不同,所以你可以花一个小时阅读官方的[Java基础知识](http://docs.oracle.com/javase/tutorial/java/index.html)。不需要那么长时间,并且在理解Java可以,不可以,不想做和不可以做的事情方面给你一个很大的提升。 – 2014-11-04 17:52:16

+0

其实java可以做我问的问题,有人确实回答了我的需求(指向最佳答案)谢谢:) – Indigo 2014-11-04 18:00:26

+2

实际上,它不能,你得到的答案是关于创建一个新的Runnable实例,它被调用来运行与调用方法的方式不同。它可以做你想做的事,但你想做的是打破不少Java最佳实践和约定=) – 2014-11-04 18:02:32

回答

-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();); 
+0

我喜欢你和你的想法!让我试试吧! :D – Indigo 2014-11-04 17:51:48

+0

你是对的!这正是我想要的!爱的感谢谢谢! :D – Indigo 2014-11-04 17:59:47

+1

@Indigo你应该也可以使用lambdas而不是匿名类,但我不知道在java中如何做到这一点。如果有其他人,请编辑答案。 – clcto 2014-11-04 17:59:57

0

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

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

public static int login(){ 

    return 0; 
} 

public static void main (String[] args){ 


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

然后,您可以更改整数到任何的返回类型的函数登录()。

+0

正如我的问题所述,我不准备改变任何函数的返回类型。 – Indigo 2014-11-04 17:51:13

+0

您没有指定函数的返回类型。如果它是无效的,答案是“不,你不能”,如果它是别的东西,那么就把** Integer **改成你函数的返回类型。 – 2014-11-04 17:53:15

+0

我提到过我的大部分功能在我的问题中都是无效的,感谢您的建议,我会仔细研究一下。 – Indigo 2014-11-04 17:56:19

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()方法,它调用其内部的Actorperform()方法。在这种情况下,它将采用优先级为URGENT的驱动程序,该驱动程序恰好运行功能returnThree()

所以这将做你所要求的。但我反对它。它只能执行没有参数的函数(或者仅仅调用具有预定参数的特定函数)。你不能通过它像Math.sqrt,因为当你需要执行它时,你无法将数字传递给该函数。

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